11
votes

SQL comme des performances avec seulement la générique (%) en tant que valeur

Je me demande quelles seraient les performances d'une requête, comme utiliser le mot-clé similaire et la carte générique comme valeur comparée à ne pas avoir de clause de la part du tout.

considère une clause de référence telle que "où un% similaire" ". Cela correspondra à toutes les valeurs possibles de la colonne 'A'. Comment cela se compare-t-il à ne pas avoir la clause WHERE?

La raison pour laquelle je demande est que j'ai une application dans laquelle l'utilisateur peut spécifier des valeurs à rechercher. Dans certains cas, l'utilisateur aimerait tous les résultats possibles. J'utilise actuellement une seule requête comme celle-ci: xxx

Les valeurs de '%' et "%" peuvent être fournies pour correspondre à toutes les valeurs possibles pour A et B. Ceci est pratique car je peux utiliser une seule requête nommée dans ma demande pour cela. Je me demande quelles sont les considérations de performance pour cela. L'optimiseur de requête réduit-il comme «%» pour simplement correspondre à tous? Je me rends compte que parce que j'utilise une requête nommée (déclaration préparée), cela peut également affecter la réponse. Je réalise que la réponse est probablement spécifique à la base de données. Donc, précisément, comment cela fonctionnerait-il dans Oracle, MS SQL Server et Derby.

L'approche suppléante de remplacement de ce type serait d'utiliser 3 requêtes distinctes en fonction de l'utilisateur saisissant la carte générique.

A est une requête générique: xxx

b est la requête générique: xxx

a et b est des cartes génériques: < Pré> xxx

pas de caractères génériques: xxx

ayant évidemment une seule requête est le plus simple et le plus facile à entretenir. Je préférerais utiliser une seule question si la performance sera toujours bonne.


3 commentaires

Je ne peux que recommander de le tester. Mais j'essaierais de rester à des requêtes simples. Ne surchargez pas la surcommande, faites deux séparément. A MON HUMBLE AVIS.


Je recommande vivement de lire l'article d'Erland sur les conditions de recherche dynamiques. C'est assez long mais je pense que cela vous donnera une perspicacité très sérieuse et utile sur le sujet. SOMMARSKOG.SE/DYN-SEARCH-2005.HTML


"Je me demande quelle serait la performance d'une requête". Réponse facile à cela est: Exécutez des tests.


11 Réponses :


2
votes

Tout SGBD qui vaut son sel dépasserait comme '%' clauses avant même d'essayer d'exécuter la requête. Je suis assez certain que j'ai vu DB2 / Z faire cela dans ses plans d'exécution.

La déclaration préparée ne doit pas faire une différence car elle devrait être transformée en réel sql avant qu'il ne reçoit Le moteur d'exécution.

mais, comme pour toutes les questions d'optimisation, mesure, ne devinez pas ! Les dabas existent parce qu'ils ajustement constamment les SGBD en fonction des données réelles (qui change au fil du temps). À un minimum nu, vous devriez faire du temps (et obtenir les plans d'exécution) pour toutes les variantes avec des données statiques appropriées pour voir s'il y a une différence.

Je sais que les requêtes comme: xxx

sont optimisés pour supprimer l'ensemble de l'ensemble de la clause avant exécution (sur DB2 de toute façon et, avant de demander, la construction est utile où vous devez supprimer l'effet de la clause WHERE mais maintenez toujours l'espace réservé aux paramètres (en utilisant BIRT avec JavaScript afin de modifier les requêtes pour les caractères génériques)).


2 commentaires

Je ne pense pas que cela soit vrai, surtout si la colonne comparée est nullable. Comme '%' ne devraient pas renvoyer ces lignes où la colonne est nulle, de sorte que les critères ne doivent donc pas les réintroduire soudainement aux résultats.


Le SGBD devrait (et est "devrait") être capable de dire si la colonne n'est pas nullable et ne pas optimiser. En tout état de cause, cela rendrait la question de l'OPS Moot, car ils ne seraient pas en mesure de le faire non plus.



1
votes

Selon la structure de la manière dont le prédicat similaire est structuré et sur le terrain, vous pourriez avoir besoin d'une numérisation de table complète. Semantiquement un "%" pourrait impliquer une numérisation de table complète mais SQL Server fait toutes sortes d'optimisation en interne sur les requêtes. La question devient donc: Est-ce que SQL Server optimise sur un prédicat similaire formé avec '%' et le jette de la clause WHERE?


0 commentaires

13
votes

SQL Server verra généralement xxx

et le traiter comme xxx

... et utilise heureusement un indice de recherche si nécessaire. Je dis 'généralement', parce que je l'ai vu ne pas faire cette simplification dans certains cas.

Si quelqu'un essaie de faire: xxx

. ..anden une demande d'index sera essentiellement impossible.

mais quelque chose d'aussi simple que: xxx

sera considéré comme équivalent à: < Pré> xxx


3 commentaires

DB2 (au moins) a le concept d'index inverse où '% Ville' est facilement optimisée (en stockant les valeurs inversées dans l'index et changeant en interne la requête à «Elliv%»). Vous pouvez imiter la même chose sur d'autres SGMS 'avec une colonne supplémentaire et des déclencheurs d'insérer / mettre à jour.


Bien sûr, mais alors% Ville% devient plus compliqué. Si vous recherchez des mots entiers, la recherche de FullText devient une option plus agréable.


+1 pour indiquer que comme '%' ne retournera que des lignes avec des valeurs non nulles.



4
votes

Vous pouvez utiliser n'importe quelle analyse de requête The DBMS propose (par exemple, Expliquez pour mysql, SET WORSHPLAN_ALL sur pour MS SQL (ou utilisez l'un des Autres méthodes ), Expliquer le plan pour pour oracle) pour voir comment la requête sera exécutée.


0 commentaires

0
votes

Et si une colonne a une valeur vide non nulle? Votre requête correspondra probablement à cela.

S'il s'agit d'une requête pour une application du monde réel, essayez d'utiliser les fonctionnalités d'indexation de texte gratuits de la plupart des bases de données SQL modernes. Les problèmes de performance deviendront insignifiants.

Un simple siénaque de Si (A b) rechercher A b sinon (a) rechercher A sinon b Rechercher b autre Dites à l'utilisateur qu'ils n'ont rien spécifié

est trivial pour maintenir et devient beaucoup plus facile à comprendre au lieu de faire des hypothèses sur l'opérateur similaire. Vous allez probablement faire cela dans l'interface utilisateur quand même lorsque vous affichez les résultats "Votre recherche d'une recherche x" ou "Votre recherche d'un B trouvé ..."


0 commentaires

0
votes

Je ne suis pas sûr de la valeur de l'utilisation d'une déclaration préparée avec le type de paramètres que vous décrivez. La raison en est que vous pourriez tromper l'optimiseur de requête dans la préparation d'un plan d'exécution qui serait complètement faux en fonction duquel des paramètres étaient «%».

Par exemple, si la déclaration a été préparée avec un plan d'exécution à l'aide de l'index sur la colonne A, mais le paramètre de colonne A s'est avéré '% "Vous pouvez rencontrer de mauvaises performances.


0 commentaires

-2
votes

une clause où "comme"% "" comme le seul prédicat se comportera exactement de la même manière que la clause du tout.


1 commentaires

Je voulais dire que cela se comportera de la même perspective de performance, mais je n'étais évidemment pas assez clair. En outre, cela n'est pas non plus vrai dans certains cas.



2
votes

Derby propose également des outils permettant d'examiner le plan de requête réel utilisé. Vous pouvez donc exécuter des expériences à l'aide de Derby et examinez le plan de requête que Derby a choisi. Vous pouvez exécuter derby avec -dderby.language.logqueryplan = true et Derby écrira le plan de requête sur derby.log, ou vous pouvez utiliser la fonction RunTimestaticistique, comme décrit ici: http://db.apache.org/ederby/docs/10.5/TUning/ctundepth853133.html

Je ne suis pas sûr que Derby élimine le "%" comme "%" à ​​l'avance, mais je ne pense pas non plus que la présence de cette clause introduira une grande partie du ralentissement de la vitesse d'exécution.

Je serais tout à fait intéressé de voir la sortie du plan de requête réelle que vous entrez dans votre environnement, avec et sans la clause de '%' en place.


0 commentaires

2
votes

Oracle 10Gr2 ne semble pas effectuer une optimisation spéciale pour cette situation, mais il reconnaît que, comme "%" exclut les nuls.

Plan hash value: 3733279756

--------------------------------------------------------------------------------
| Id  | Operation          | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |           |     1 |    10 |     3   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |           |     1 |    10 |            |          |
|*  2 |   TABLE ACCESS FULL| LIKE_TEST |  1000 | 10000 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("COL1" IS NOT NULL)


0 commentaires

1
votes

Un aspect que je pense manque à la discussion est le fait que l'OP souhaite utiliser une déclaration préparée. Au moment où la déclaration est préparée, la base de données / optimiseur ne sera pas en mesure de déterminer les simplifications dont les autres ont mentionné et ne pourront donc pas optimiser le A comme '%' comme le réel la valeur ne sera pas connue à la préparation du temps.

donc:

  • Lorsque vous utilisez des énoncés préparés, disposez de quatre déclarations différentes (0, uniquement A, seulement B, B, à la fois) et utilisez le besoin approprié en cas de besoin
  • Voyez si vous obtenez une meilleure performance lorsque vous n'utilisez pas une instruction préparée lorsque vous collez une seule déclaration (bien que ce soit assez facile de ne pas inclure «vide»)

0 commentaires

4
votes

J'espérais qu'il y aurait une réponse de manuel à cela, mais il semble que cela varie en grande partie avec différents types de base de données. La plupart des réponses ont indiqué que je devrais exécuter un test de sorte que c'est exactement ce que j'ai fait.

Mon application ciblait principalement les bases de données Derby, MS SQL et Oracle. Depuis que Derby peut être exécuté intégré et est facile à configurer, j'ai testé la performance à ce début. Les résultats étaient surprenants. J'ai testé le pire des cas de scénario contre une table assez grande. J'ai exécuté le test 1000 fois et ai fait la moyenne des résultats. P>

Query 1: P>

SELECT * FROM TableName WHERE a LIKE ? AND b LIKE ?


0 commentaires