Pagina 1 di 3 1 2 3 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 23
  1. #1
    Utente di HTML.it L'avatar di james
    Registrato dal
    Jun 2002
    Messaggi
    1,481

    ottimizzare una query con una join tra tabelle con milioni di record

    Ho due tabelle, una rappresenta l'accesso ad un sito, la sessione per capirci, e c'è una colonna "utente" che identifica l'ID utente, l'altra rappresenta le pagine visitate dall'utente internamente ad ogni singola sessione. La tabella "pagine_visitate" è legata alla tabella "sessioni" da una chiave esterna.

    Quando vado a fare il count di tutte le visite fatte da un utente, quindi non le sessioni, ma il count delle pagine visitate per tutte le sessioni a lui riferite, i tempi della query è circa 40 secondi...Sto cercando di ottimizzarla ma non ne vengo fuori. La query è questa:
    Codice PHP:
    SELECT COUNT(*) as visite FROM accessi LEFT JOIN sessioni ON accessi.sessione_id=sessioni.id WHERE sessioni.user_id='6' 
    la chiave accessi.sessione_id è un indice, così come sessioni.user_id ovviamente. Ho fatto un EXPLAIN, praticamente mysql prima seleziona tutte le sessioni applicando la WHERE SIMPLE e nel caso di alcuni utenti vengono fuori 3 mln di record, poi procede con la JOIN, ma i tempi sono enormi! Ho provato a cambiare la query così sperando di ottenere risultati diversi:
    Codice PHP:
    SELECT COUNT(*) as visite FROM accessi WHERE sessione_id IN SELECT id FROM sessioni WHERE user_id='6'); 

    Pensavo che così facendo ci metteva un attimo a scremare la SELECT annidata con la sola WHERE, ed infatti fa abbastanza subito se testo quella sola query con un LIMIT, ma se non uso il LIMIT e faccio tirare giù tutti i 3milioni di risultati per poi a incrociare 3 milioni di istanze con la causola IN...è comunque un bagno di sangue. Secondo voi c'è modo di ottimizzare una query del genere?

  2. #2
    prova con

    SELECT COUNT(*) as visite FROM accessi LEFT JOIN sessioni ON accessi.sessione_id=sessioni.id AND sessioni.user_id='6'

  3. #3
    Utente di HTML.it L'avatar di james
    Registrato dal
    Jun 2002
    Messaggi
    1,481
    Quote Originariamente inviata da optime Visualizza il messaggio
    prova con

    SELECT COUNT(*) as visite FROM accessi LEFT JOIN sessioni ON accessi.sessione_id=sessioni.id AND sessioni.user_id='6'
    è esattamente la stessa cosa, anche l'EXPLAIN è proprio identico

  4. #4
    la colonna session_id è indicizzata?

  5. #5
    Utente di HTML.it L'avatar di james
    Registrato dal
    Jun 2002
    Messaggi
    1,481
    Quote Originariamente inviata da optime Visualizza il messaggio
    la colonna session_id è indicizzata?
    sì certo

  6. #6
    scusa, intendevo la sessioni.user_id

  7. #7
    Utente di HTML.it L'avatar di james
    Registrato dal
    Jun 2002
    Messaggi
    1,481
    Se faccio la COUNT della sola tabella sessioni (tralasciando la tabella accessi) i tempi sono sotto il secondo
    Codice PHP:
    SELECT COUNT(*) as visite FROM sessioni WHERE user_id='6'

  8. #8
    Utente di HTML.it L'avatar di james
    Registrato dal
    Jun 2002
    Messaggi
    1,481
    Quote Originariamente inviata da james Visualizza il messaggio
    sì certo
    Sì anche quel campo ovviamente

  9. #9
    Utente di HTML.it L'avatar di james
    Registrato dal
    Jun 2002
    Messaggi
    1,481
    Quote Originariamente inviata da james Visualizza il messaggio
    Se faccio la COUNT della sola tabella sessioni (tralasciando la tabella accessi) i tempi sono sotto il secondo
    Codice PHP:
    SELECT COUNT(*) as visite FROM sessioni WHERE user_id='6'
    Il problema sorge dalla JOIN, il che mi fa pensare che (non so come lavora mysql praticamente) che prima faccia la SELECT della condizione come dice l'EXPLAIN, quindi tira fuori tutte le istanze di sessioni in cui la condizione sessioni.user_id='6' è verificata, il che sono circa 3 milioni di record, poi per ciascuno di essi fa 3milioni di controlli per estrarre (e contare) quante istanze di "accessi" sono legate ad ogni singolo risultato della prima parte della SELECT, per cui è come se facesse 3mln(record estratti da sessioni per sessioni.user_id='6')*9mln(record totali della tabella "accessi") per cui i tempi si elevano esponenzialmente.

  10. #10
    ... i miei due centesimi;

    codice:
    SELECT COUNT(*) as visite FROM accessi LEFT JOIN (select * from sessioni WHERE sessioni.user_id='6') as q ON accessi.sessione_id=q.sessioni.id
    HTH

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.