C'è stato un dibattito al lavoro di recente nel modo più efficiente per cercare un database MS SQL usando LIKE
e caratteri jolly. Stiamo confrontando utilizzando %abc%
, %abc
e abc%
. Una persona ha affermato che è necessario avere sempre il carattere jolly alla fine del termine (abc%
). Quindi, secondo loro, se volessimo trovare qualcosa che finisse in "abc" sarebbe più efficiente usare "reverse (column) LIKE reverse" (% abc).Ricerca jolly SQL - Efficienza?
ho creato un test utilizzando SQL Server 2008 (R2) per confrontare ciascuna delle seguenti affermazioni:
select * from CLMASTER where ADDRESS like '%STREET'
select * from CLMASTER where ADDRESS like '%STREET%'
select * from CLMASTER where ADDRESS like reverse('TEERTS%')
select * from CLMASTER where reverse(ADDRESS) like reverse('%STREET')
CLMASTER detiene circa 500.000 record, ci sono circa 7.400 gli indirizzi che terminano "Street", e circa 8.500 indirizzi che contengono "Street", ma non necessariamente alla fine. Ogni test ha richiesto 2 secondi e tutti hanno restituito lo stesso numero di righe, ad eccezione di %STREET%
, che ha riscontrato un aumento di circa 900 risultati in quanto ha rilevato gli indirizzi che avevano un numero di appartamento alla fine.
Poiché il test di SQL Server non ha mostrato alcuna differenza nel tempo di esecuzione mi sono trasferita in PHP in cui ho usato il seguente codice, il passaggio in ogni dichiarazione, per eseguire più test in fretta:
<?php
require_once("config.php");
$connection = odbc_connect($connection_string, $U, $P);
for ($i = 0; $i < 500; $i++) {
$m_time = explode(" ",microtime());
$m_time = $m_time[0] + $m_time[1];
$starttime = $m_time;
$Message=odbc_exec($connection,"select * from CLMASTER where ADDRESS like '%STREET%'");
$Message=odbc_result($Message,1);
$m_time = explode(" ",microtime());
$m_time = $m_time[0] + $m_time[1];
$endtime = $m_time;
$totaltime[] = ($endtime - $starttime);
}
odbc_close($connection);
echo "<b>Test took and average of:</b> ".round(array_sum($totaltime)/count($totaltime),8)." seconds per run.<br>";
echo "<b>Test took a total of:</b> ".round(array_sum($totaltime),8)." seconds to run.<br>";
?>
I risultati di questo test era ambiguo quanto i risultati durante i test in SQL Server.
%STREET
completato in 166.5823 secondi (media 3333 per query) e una media di 500 risultati trovati in .0228.
%STREET%
completato in 149.4500 secondi (0,289 media per query) e una media di 500 risultati trovati in .0177. (Tempo più rapido per risultato perché trova più risultati rispetto agli altri, in tempi simili.)
reverse(ADDRESS) like reverse('%STREET')
completato in 134.0115 secondi (.2680 media per query) e una media di 500 risultati trovati in .0183 secondi.
reverse('TREETS%')
completato in 167,6960 secondi (.3354 media per query) e una media di 500 risultati trovati in .0229.
Ci aspettavamo questo test per dimostrare che %STREET%
sarebbe il più lento nel complesso, mentre in realtà era il più veloce da eseguire e aveva il miglior tempo medio per restituire 500 risultati. Mentre il suggerimento reverse('%STREET')
è stato il più veloce da eseguire nel complesso, ma è stato un po 'più lento nel tempo per restituire 500 risultati.
divertimento Extra: Un collega ha profiler sul server mentre stavamo eseguendo i test e ha scoperto che l'uso del doppio jolly ha prodotto un significativo aumento l'utilizzo della CPU, mentre le altre prove sono state in 1-2% l'uno dall'altro.
Ci sono esperti di SQL Efficiency che possono spiegare perché avere il carattere jolly alla fine della stringa di ricerca sarebbe una pratica migliore rispetto all'inizio e forse perché la ricerca con caratteri jolly all'inizio e alla fine della stringa era più veloce che avere il jolly solo all'inizio?
Did cancelli i buffer e la cache prima di ogni test? –
Sì, prima che ciascuna query venisse esaminata, abbiamo riavviato il server per assicurarsi che fosse un test corretto. – Jeremy1026
L'approccio reverse() imporrà una scansione della tabella poiché ogni riga deve essere invertita, solitamente utilizzata con prefissi-caratteri jolly + una colonna inversa pre-calcolata –