6
votes

SQL complexe rejoindre le groupe par

J'essaie d'optimiser une requête qui prend beaucoup de temps. L'objectif de la requête est d'obtenir le meilleur F2 similaire. (Spécialement la mesure de similitude) Ceci est un exemple de ce que j'ai: xxx

maintenant si j'exécute cette requête: xxx

La table a 1m + rangées. Quelle serait une meilleure façon de faire cela?


7 commentaires

Quels index avez-vous pour cette table?


J'ai du mal à comprendre le but de la requête, pouvez-vous aussi expliquer?


L'indice non clusteré comprend F1, F2, F3


Objectif de la requête Get Meilleur Similaire F2. (Spécialement la mesure de similitude)


Voulez-vous dire «mesure de similitude spatiale»?


Je comprends que vos données sont du texte, mais je ne vois aucune référence en ligne pour la mesure de similarité "spécialement" que vous avez mentionnée, alors j'essaie de deviner à ce que ce premier mot devrait être.


Pourriez-vous fournir d'autres informations en vérifiant le plan d'exécution. Quelle partie de la requête prenant plus de temps.


5 Réponses :


3
votes

Vous pouvez également écrire votre requête dans ce formulaire et, comme vous en avez une sélection, votre temps de récupération sera réduit

SELECT  Test_1.F2, COUNT(Test_1.F1) AS Cnt 
FROM    Test 
INNER JOIN Test AS Test_1 ON Test.F1 = Test_1.F1 AND Test.F3 = Test_1.F3 
WHERE   (Test.F2 = 'B') 
GROUP BY Test_1.F2


2 commentaires

Votre requête en table réelle prenant une longue période égale à ma requête.6 sec.


Réécrire une requête à utiliser une seule sélection au lieu de deux ne garantira pas qu'il finira plus tôt. Si vous voulez savoir comment un changement spécifique à une requête SQL aura une incidence sur son coût estimé, les rapports produits par la requête expliquent l'utilitaire vous montreront quelles parties de la requête sont chères (et pourquoi).



1
votes

Si votre table d'essai a 1 m + lignes, la table temporaire jointe sur laquelle vous auriez facilement des centaines de millions de lignes.

Cela fonctionnerait dans MySQL mais pas sur SQL-Server AFAIK: P>

SELECT F2,COUNT(*)
FROM Test AS B 
WHERE (B.F1,B.F3) IN (
  SELECT F1,F3 FROM Test
  WHERE F2='B') 
GROUP BY F2


1 commentaires

d'accord; BTW Je n'ai pas pu exécuter votre requête originale sur SQLFIDDLE's SQL-Server, alors je pensais que vous expérimeniez sur MySQL



2
votes

Une recherche filtrée pour toutes les lignes où F2 = 'B' entraînera une numérisation de table complète, sauf si vous créez un index qui a F2 comme première ou unique colonne. Plus bas, la condition de jointure implique des colonnes F1 et F3, que vous mentionnez faites déjà partie d'un index qui commence par F1.

Je remarque également que la première partie de votre requête n'élimine pas les doublons pour l'ensemble de (T1, T3) où T2 = 'B', comme on pouvait s'attendre lors de l'intersection qui a reculé contre un autre sous-ensemble de la même table. Vous avez peut-être une raison de faire cela, mais nous ne pouvons pas savoir avec certitude que vous ne fournissez aucun détail sur l'algorithme de mesure de similarité que vous essayez de mettre en œuvre.

Votre clause par affecte également le temps d'exécution de la requête en encourageant un tri interne potentiellement important sur le jeu de résultats final.


1 commentaires

J'apprécie le ✓, mais je suis toujours intéressé par l'algorithme que vous utilisez sur vos données. Si vous avez un moment pour établir les étapes en détail, nous pourrions vous aider à développer une requête plus efficace et directe.



3
votes

Voici une autre façon d'écrire votre requête. Près de la réponse de Guido annoncable dans MS SQL.

WITH Filtered AS (SELECT DISTINCT F1,F3 FROM Test WHERE F2='B')
SELECT B.f2,COUNT(*) AS CNT
  FROM Test B
       INNER JOIN Filtered
           ON B.F1 = Filtered.F1 AND B.F3 = Filtered.F3
 GROUP BY B.F2
 ORDER BY CNT DESC


1 commentaires

Ma requête n'a pas de bug, le nombre de F2 = "B" devrait être 8 et distinct est davantage et après la suppression qui est égale à ma requête dans le temps.



1
votes

Je me rends compte que cela a déjà été répondu, mais je pense que cette approche pourrait être beaucoup plus rapide, en particulier si F1 et F3 ont de nombreuses valeurs dupliquées: xxx

si F1 et F3 n'ont pas Très nombreuses combinaisons, puis la première sous-requête devrait réduire à quelques centaines de lignes. (Votre exemple de données contient une seule lettre majuscule, le nombre de combinaisons serait de 576 si toutes les lettres sont utilisées.) SQL Server fera probablement une fusion ou une jointure de hachage sur le résultat qui devrait bien fonctionner.

Vous pouvez également le faire sans que la jointure et le groupe en utilisant des fonctions Windows: xxx

Les fonctions de la fenêtre fonctionnent souvent mieux car elles fonctionnent sur des morceaux plus petits des données.


0 commentaires