Sto ottimizzando molte query esistenti nel mio progetto. La soluzione di Quassnoi mi ha aiutato ad accelerare molto le domande! Tuttavia, trovo difficile incorporare la suddetta soluzione in tutte le query, specialmente per query complicate che coinvolgono molte sottoquery su più tabelle di grandi dimensioni.
Quindi sto usando una soluzione meno ottimizzata. Fondamentalmente funziona allo stesso modo della soluzione di Quassnoi.
SELECT accomodation.ac_id,
accomodation.ac_status,
accomodation.ac_name,
accomodation.ac_status,
accomodation.ac_images
FROM accomodation, accomodation_category
WHERE accomodation.ac_status != 'draft'
AND accomodation.ac_category = accomodation_category.acat_id
AND accomodation_category.acat_slug != 'vendeglatohely'
AND ac_images != 'b:0;'
AND rand() <= $size * $factor / [accomodation_table_row_count]
LIMIT $size
$size * $factor / [accomodation_table_row_count]
calcola la probabilità di scegliere una riga casuale. Il rand () genererà un numero casuale. La riga verrà selezionata se rand () è minore o uguale alla probabilità. Ciò esegue efficacemente una selezione casuale per limitare la dimensione della tabella. Poiché esiste la possibilità che restituisca un valore inferiore al conteggio limite definito, è necessario aumentare la probabilità per assicurarsi di selezionare un numero sufficiente di righe. Quindi moltiplichiamo $ size per $ factor (di solito imposto $ factor = 2, funziona nella maggior parte dei casi). Finalmente facciamo il filelimit $size
Il problema ora sta elaborando accomodation_table_row_count . Se conosciamo la dimensione della tabella, POTREBBE codificare la dimensione della tabella. Questo sarebbe il più veloce, ma ovviamente non è l'ideale. Se stai usando Myisam, ottenere il conteggio delle tabelle è molto efficiente. Dato che sto usando innodb, sto solo facendo un semplice conteggio + selezione. Nel tuo caso, sarebbe simile a questo:
SELECT accomodation.ac_id,
accomodation.ac_status,
accomodation.ac_name,
accomodation.ac_status,
accomodation.ac_images
FROM accomodation, accomodation_category
WHERE accomodation.ac_status != 'draft'
AND accomodation.ac_category = accomodation_category.acat_id
AND accomodation_category.acat_slug != 'vendeglatohely'
AND ac_images != 'b:0;'
AND rand() <= $size * $factor / (select (SELECT count(*) FROM `accomodation`) * (SELECT count(*) FROM `accomodation_category`))
LIMIT $size
La parte difficile sta elaborando la giusta probabilità. Come puoi vedere, il codice seguente calcola in realtà solo la dimensione approssimativa della tabella temporanea (in effetti, troppo approssimativa!): (select (SELECT count(*) FROM accomodation) * (SELECT count(*) FROM accomodation_category))
Ma puoi perfezionare questa logica per dare un'approssimazione della dimensione della tabella più vicina. Nota che è meglio selezionare OVER piuttosto che sotto-selezionare le righe. cioè se la probabilità è impostata su un valore troppo basso, rischi di non selezionare abbastanza righe.
Questa soluzione è più lenta della soluzione di Quassnoi poiché dobbiamo ricalcolare la dimensione della tabella. Tuttavia, trovo questa codifica molto più gestibile. Questo è un compromesso tra accuratezza + prestazioni e complessità di codifica . Detto questo, su tabelle di grandi dimensioni questo è ancora di gran lunga più veloce di Order by Rand ().
Nota: se la logica della query lo consente, eseguire la selezione casuale il prima possibile prima di qualsiasi operazione di join.