SQL Wildcard Search - Efficacité?
Il y a eu un débat au travail récemment à la manière la plus efficace pour rechercher une base de données MS SQL à l'aide de LIKE
et des caractères génériques. Nous le comparons à l'aide de %abc%
%abc
et abc%
. Une personne a dit que vous devriez toujours avoir le générique à la fin de la période (abc%
). Donc, selon eux, si nous voulions trouver quelque chose qui s'est terminée en "abc", il serait plus efficace d'utiliser la fonction "inverse(colonne) inverse (en% "abc").
- Je configurer un test à l'aide de SQL Server 2008 (R2) pour comparer chacun des énoncés suivants:
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 détient environ 500 000 enregistrements, il y a quelque 7 400 adresses de fin "de la Rue", et environ 8 500 adresses "de la Rue", mais pas nécessairement à la fin. Chaque essai a pris 2 secondes, et ils ont tous retourné le même nombre de lignes à l'exception de %STREET%
qui a trouvé un supplément de 900 ou alors des résultats car il a ramassé les adresses qui ont un numéro d'appartement sur la fin.
Depuis le Serveur SQL server test n'a montré aucune différence dans le temps d'exécution, j'ai déménagé en PHP où j'ai utilisé le code suivant, la commutation dans chaque état, pour exécuter plusieurs tests rapidement:
<?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>";
?>
Les résultats de ce test était à peu près aussi ambigu que les résultats lors de l'essai de SQL Server.
%STREET
achevé en 166.5823 secondes (.3331 moyenne par requête), et en moyenne 500 résultats présents dans .0228.
%STREET%
achevé en 149.4500 secondes (.2989 moyenne par requête), et en moyenne 500 résultats présents dans .0177. (Plus rapide temps par la suite parce qu'il trouve plus de résultats que les autres, en même temps.)
reverse(ADDRESS) like reverse('%STREET')
achevé en 134.0115 secondes (.2680 moyenne par requête), et en moyenne 500 résultats trouvés dans .0183 secondes.
reverse('TREETS%')
achevé en 167.6960 secondes (.3354 moyenne par requête), et en moyenne 500 résultats présents dans .0229.
Nous nous attendions à ce que ce test montrent que %STREET%
serait le plus lent dans l'ensemble, alors que c'était en fait le plus rapide à exécuter, et qui a la meilleure moyenne de temps de retour de 500 résultats. Alors que le suggère reverse('%STREET')
a été le plus rapide à exécuter dans l'ensemble, mais un peu plus lentement dans le temps pour revenir 500 résultats.
Plus de plaisir: Un collègue a couru profiler sur le serveur alors que nous étions à en exécuter les tests et constaté que l'utilisation de la double joker a produit une augmentation significative de l'utilisation de l'UC, tandis que les autres tests ont été dans un délai de 1-2% de l'autre.
Y a-SQL experts de l'Efficacité que peut expliquer pourquoi le générique à la fin de la chaîne de recherche serait préférable que le début, et peut-être pourquoi la recherche avec des caractères génériques au début et à la fin de la chaîne a été plus rapide que d'avoir le générique juste au début?
source d'informationauteur Jeremy1026 | 2012-08-03
Vous devez vous connecter pour publier un commentaire.
Avoir le générique à la fin de la chaîne, comme
'abc%'
permettrait de si cette colonne ont été indexés, comme il serait capable de demander directement aux enregistrements qui commencent avec'abc'
et ignorer tout le reste. Avoir la carte sauvage au début signifie qu'il a un look à chaque ligne, sans tenir compte de l'indexation.Bon article ici avec plus d'explication.
Uniquement des caractères génériques à la fin d'une
chaîne de caractères va utiliser un index.
Vous devriez regarder à l'aide de FTS
Contient
si vous souhaitez améliorer la vitesse de jokers à l'avant et à l'arrière d'une chaîne de caractères. Aussi voir cette SORTE de post concernant le rapport Contient Comme.De Microsoft il est plus efficace de laisser la clôture générique parce qu'il peut, le cas échéant, utiliser un index plutôt que d'effectuer une analyse. Pensez à la façon dont la recherche pourrait fonctionner, si vous n'avez aucune idée de ce qui est avant, alors vous avez à tout analyser, mais si vous êtes seulement à la recherche du bout de la queue, alors vous pouvez commander les lignes et même possible (en fonction de ce que vous cherchez) faire un quasi-binaire de recherche.
Ainsi, la citation ci-dessus explique aussi pourquoi il y avait un énorme processeur pic lors de l'exécution de deux jokers. Il terminé plus rapidement que par le hasard, car il y a suffisamment de puissance pour couvrir l'inefficacité. Lorsque vous essayez de déterminer la performance sur une requête que vous souhaitez regarder à l'exécution de la requête plutôt que les ressources du serveur, car ceux-ci peuvent être trompeuses. Si j'ai un serveur avec suffisamment de puissance pour servir une météo vain, et je suis de l'exécution de requêtes sur des tables aussi petit que 500 000 lignes les résultats vont être trompeuse.
Moins le fait que Microsoft a cité votre réponse, quand vous faites l'analyse de la performance, envisager de prendre le plongeon dans l'apprentissage de la lecture le plan d'exécution. C'est un investissement et très sec, mais il en vaut la peine dans le long terme.
En bref bien que, celui qui indique que la fuite générique seulement est plus efficace, il est correct.
Dans MS SQL, si vous voulez avoir les noms de ceux qui sont en terminant par "ABC", alors u peut avoir de la requête comme ci-dessous(à supposer que nom de la table est
student
)de sorte que ces noms qui se termine par 'A' ,'B','C'.
2) si tu veux avoir des noms qui commencent avec " ABC " signifie-
3) si tu veux avoir des noms qui en moyenne ont 'ABC'