C'est une question simple pour laquelle je n'arrive pas à trouver la réponse.
En termes de performances, si j'ai une WHERE
clause telle que a=0 and b=0 and ... z=0
, gagnerais-je des performances si je remplaçais cette condition par a+b+...+z=0
?
En d'autres termes, y a-t-il un gain de performances en remplaçant les éléments suivants
Select *
From MyTable
Where A=0 and B=0 and C=0 and D=0...
Avec
Select *
From MyTable
Where A+B+C+D=0...
Je sais que cela peut dépendre des index, mais à cet effet, disons simplement qu'aucun index n'existe. L'opérateur arithmétique (+) fonctionne-t-il mieux qu'un opérateur logique "OU" ou "ET"?
J'ai l'impression que l'ajout fonctionne mieux que plusieurs conditions avec des ET ou des OU.
Résultats de test
Sur un tableau de 4,2 millions de lignes
Lignes de retour Où A = 0 B = 0 et C = 0 -> 351748 Lignes
L'addition (A + B + C = 0) a pris 5 secondes tandis que les conditions logiques A = 0 et B = 0 et C = 0 ont pris 11 secondes.
D'autre part
Lignes de retour Où A <> 0 B <> 0 ou C <> 0 -> 3829750 Lignes 58 secondes
Lignes de retour Où F65 + F67 + f64 <> 0 -> 3829750 Lignes 57 secondes
Pour la RO, il semble qu'il n'y ait pas de différence significative.
Je suis d'accord avec gbn:
Si A est -1 et B est 1, A + B = 0 mais A = 0 et B = 0 est faux
et avec AMtwo:
ABS (A) + ABS (B) + ABS (C) + ABS (D) ... Même si vous n'attendez que des valeurs positives, si la colonne accepte des valeurs négatives, vous devez supposer que vous pourriez en rencontrer un
Les résultats sont très impressionnants, comme je le pensais, il semble que l'addition soit beaucoup plus rapide que les opérateurs logiques.
A = flottant, B = argent et C = flottant. La requête utilisée est la suivante. Dans mon cas, tous sont des nombres positifs. Pas d'index. Il est logique dans mon esprit que l'addition soit plus rapide que les conditions logiques!
Réponses:
Dans votre question, vous détaillez certains tests que vous avez préparés où vous "prouvez" que l'option d'ajout est plus rapide que la comparaison des colonnes discrètes. Je soupçonne que votre méthodologie de test peut être défectueuse de plusieurs manières, comme l'ont fait référence à @gbn et @srutzky.
Tout d'abord, vous devez vous assurer que vous ne testez pas SQL Server Management Studio (ou le client que vous utilisez). Par exemple, si vous exécutez une
SELECT *
table à partir de 3 millions de lignes, vous testez principalement la capacité de SSMS à extraire des lignes de SQL Server et à les afficher à l'écran. Il vaut mieux utiliser quelque chose commeSELECT COUNT(1)
qui annule la nécessité de tirer des millions de lignes sur le réseau et de les afficher à l'écran.Deuxièmement, vous devez connaître le cache de données de SQL Server. En règle générale, nous testons la vitesse de lecture des données du stockage et du traitement de ces données à partir d'un cache froid (c'est-à-dire que les tampons de SQL Server sont vides). Parfois, il est logique de faire tous vos tests avec un cache chaud, mais vous devez aborder vos tests de manière explicite dans cet esprit.
Pour un test de cache froid, vous devez exécuter
CHECKPOINT
etDBCC DROPCLEANBUFFERS
avant chaque exécution du test.Pour le test que vous avez demandé dans votre question, j'ai créé le banc d'essai suivant:
Cela renvoie un nombre de 260 144 641 sur ma machine.
Pour tester la méthode "addition", je lance:
L'onglet messages affiche:
Pour le test "colonnes discrètes":
encore une fois, dans l'onglet messages:
D'après les statistiques ci-dessus, vous pouvez voir la deuxième variante, avec les colonnes discrètes par rapport à 0, le temps écoulé est environ 10 secondes plus court et le temps CPU est environ 6 fois moins. Les longues durées de mes tests ci-dessus sont principalement le résultat de la lecture d'un grand nombre de lignes à partir du disque. Si vous réduisez le nombre de lignes à 3 millions, vous voyez que les ratios restent à peu près les mêmes, mais les temps écoulés chutent sensiblement, car les E / S disque ont beaucoup moins d'effet.
Avec la méthode "Addition":
Avec la méthode des "colonnes discrètes":
Qu'est-ce qui fera vraiment une grande différence pour ce test? Un index approprié, tel que:
La méthode "d'addition":
La méthode des "colonnes discrètes":
Le plan d'exécution pour chaque requête (avec l'index ci-dessus en place) est assez révélateur.
La méthode "addition", qui doit effectuer un scan de l'index entier:
et la méthode des "colonnes discrètes", qui peut rechercher la première ligne de l'index où la colonne d'index de tête
A
, est nulle:la source
Disons que vous avez un index sur A, B, C et D. Peut également être filtré.
Cela est plus susceptible d'utiliser l'index que l'addition.
Dans d'autres nouvelles, si A est -1 et B est 1,
A+B=0
c'est vrai maisA=0 and B=0
c'est faux.la source
(Veuillez noter que cette réponse a été soumise avant que tout test ne soit noté dans la Question: le texte de la Question se terminait juste au-dessus de la section Résultats du test .)
Je suppose que les
AND
conditions distinctes seraient préférées car l'optimiseur serait plus susceptible de court-circuiter le fonctionnement si un seul d'entre eux n'est pas égal à 0, sans avoir besoin de faire un calcul au préalable.Néanmoins, comme il s'agit d'une question de performances, vous devez d'abord configurer un test pour déterminer la réponse sur votre matériel. Signalez ces résultats, montrez votre code de test et demandez à d'autres de le vérifier pour vous assurer qu'il s'agit d'un bon test. Il peut y avoir d'autres facteurs dignes de considération auxquels vous n'avez pas pensé.
la source
Un raisonnement général, si vous n'avez pas d'index à portée de main, je ne pense pas que ce soit très important laquelle des deux solutions que vous choisissez, les deux fonctionneront mal. Si vous avez en revanche un index sur une ou plusieurs des colonnes du prédicat, la première sera probablement plus performante que la seconde, car la seconde ne pourra probablement pas utiliser le ou les index.
Les disjonctions (OR) fonctionnent généralement moins bien que les conjonctions (AND), mais même si vous avez une requête avec des disjonctions, je mettrai mon argent sur la première.
la source
Non, ça ne l'est pas. Cette (sorte de) question est ce qui afflige de nombreux administrateurs de bases de données et développeurs de logiciels jour après jour, et c'est tout sauf trivial.
Oui, tu ne le feras pas. Du moins pas une réponse générale. Tout d'abord, cela dépendra énormément du SGBDR que vous utilisez (OK, vous utilisez sql-server , mais quand même). Il peut même changer lorsque vous passez d'une version de votre SGBDR à la suivante.
Ensuite, cela peut dépendre de n'importe quelle quantité d'autres petits détails, par exemple comment votre base de données stocke les données, si vous avez des sous-sélections / jointures qui confondent le problème pour l'optimiseur de plan, etc. L'optimiseur peut vous donner différents plans d'exécution selon sur le nombre de lignes que vous avez ...
Faire un test du monde réel est généralement le seul moyen utile de résoudre des questions comme celle-ci. De plus, tout gain obtenu grâce à des optimisations "mystérieuses" comme celle-ci est généralement décuplé par un choix intelligent d'index, donc je ne prendrais pas la peine de passer trop de temps dessus, avant qu'une utilisation des index ne soit vraiment exclue.
la source
Cela peut être évident, mais si les colonnes le sont
INT
, alors ellesa+b+c
pourraient être égales à zéro même lorsqu'aucune d'entre elles n'est réellement nulle. Vous testez deux choses différentes!la source