Comment interroger plus rapidement cette vue d'enregistrement de 20 millions d'enregistrements?

14

Pour une fonctionnalité de recherche, j'utilise une vue qui contient les enregistrements de toutes les tables dans lesquelles je dois rechercher. La vue compte près de 20 millions d'enregistrements. Les recherches contre ce point de vue prennent trop de temps.

Où dois-je chercher pour améliorer les performances de cette vue?

La définition approximative de la vue est ci-dessous. Il comprend treize tables et une trentaine de champs.

CREATE VIEW [dbo].[v_AllForSearch]
AS
SELECT 
  FT.firstField AS [firstField]
, FT.fld_primary AS [fld_primary]
, FT.fld_thirdField AS [thirdField]
, FT.fld_fourthField AS [fourthField]           
, ISNULL(ST.[fld_firstSearchField],'') AS [firstSearchField]
, ISNULL(TT.[fld_thirdSearch],'') AS thirdSearch
, ISNULL(TT.[fld_fourthSearch],'')AS fourthSearch
, ISNULL(TT.[fld_fifthSearch],'')AS fifthSearch
, ISNULL(FRT.[fld_sixthSearch],'') As [sixthSearch]
, ISNULL(FRT.[fld_seventhSearch],'') AS [seventhSearch]
, ISNULL(FRT.[fld_eightSearch],'')AS [eightSearch]
, ISNULL(FIT.[fld_nineSearch],'') AS [nineSearch]
, ISNULL(SIT.[fld_tenthSearch],'')AS [tenthSearch]
, ISNULL(SET.[fld_eleventhSearch],'') AS [eleventhSearch]
, ISNULL(ET.[twelthSearch],'')AS [twelthSearch]
, ISNULL(NT.[thirteenthSearch],'')AS [thirteenthSearch]
, ISNULL(NT.[fourteenSearch],'') AS [fourteenSearch]
, ISNULL(NT.[fifteenSearch],'') AS [fifteenSearch]
, ISNULL(NT.[sxteenSearch],'')  AS [sxteenSearch]
, ISNULL(NT.[seventeenSearch],'') AS [seventeenSearch]
, ISNULL(NT.[eighteenSearch],'')AS [eighteenSearch]
, ISNULL(TT.[ninteenSearch],'') AS [ninteenSearch]
, ISNULL(ELT.[twentySearch],'') AS [twentySearch]
, ISNULL(ELT.[twentyOneSearch],'') AS [twentyOneSearch]
, ISNULL(TWT.[twentyTwoSearch],'') AS [twentyTwoSearch]
, ISNULL(THT.twentyThree,'') AS [twentyThree]
, ISNULL(THT.twentyFour,'') AS [twentyFour]
, ISNULL(THT.twentyFive,'') AS [twentyFive]
, ISNULL(THT.twentySix,'') AS [twentySix]
FROM 
      tblFirstTable AS FT         
      LEFT JOIN [tblSecondTable] AS ST 
            ON ST.[fld_primary] = FT.[fld_primary]        
      LEFT JOIN [tblThirdTable] AS TT 
            ON TT.[fld_primary] = FT.[fld_primary]        
      LEFT JOIN [tblFourthTable] AS FRT 
            ON FRT.[fld_primary] = FT.[fld_primary]       
      LEFT JOIN [tblFifthTable] AS FIT 
            ON FIT.[fld_primary] = FT.[fld_primary]       
      LEFT JOIN [tblSixthTable] AS SIT 
            ON SIT.[fld_primary] = FT.[fld_primary]       
      LEFT JOIN [tblSeventhTable] AS SET 
            ON SET.[fld_primary] = FT.[fld_primary]       
      LEFT JOIN [tblEighthTable] AS ET 
            ON ET.[fld_primary] = FT.[fld_primary] 
      LEFT JOIN [tblNinthTable] AS NT 
            ON NT.[fld_primary] = FT.[fld_primary]        
      LEFT JOIN [tblELTnthTable] AS TT 
            ON TT.[fld_primary] = FT.[fld_primary]        
      LEFT JOIN [tblEleventhTable] AS ELT 
            ON ELT.[fld_primary] = FT.[fld_primary]       
      LEFT JOIN [tblTwelthTable] AS TWT 
                            ON TWT.[fld_id] = ELT.[fld_id]  
              LEFT JOIN [tblThirteenthTable] AS THT
            ON THT.[firstField]= FT.[firstField]
WHERE fld_Status ..
balu
la source

Réponses:

9

Une vue est une macro qui se développe. Donc, si votre vue est un JOIN de 2 tables, le plan d'exécution affichera les 2 tables. La vue est transparente.

Cela ne s'applique pas si la vue est indexée / matérialisée. Cependant, vous ne poseriez pas cette question.

Alors, que dit le plan d'exécution? Le DTA? Index dmv manquant? Requête DMV la plus chère?

gbn
la source
Il pourrait poser la question pour une vue matérialisée et ne pas réaliser qu'elle est généralement implémentée comme une simple table, elle peut donc être indexée, etc.
Joe
@Joe: peut-être, mais OP ne demanderait pas de l'aide s'ils connaissaient les différences ...
gbn
La question est balisée pour MS SQL Server donc plutôt que des "vues matérialisées" nous devrions parler de "vues indexées";)
AndrewSQL
1
@AndrewSQL: je l'ai fait. Mais nous devons prendre en compte les formes de vie inférieures ...
gbn
6

Sans plus de détails sur la vue et les tables, la réponse est "cela dépend", mais vous pouvez commencer à regarder la clause WHERE de votre vue pour les champs qui peuvent nécessiter des index.

ggponti
la source
1
Mais j'avais l'impression que les vues en général ne profitent pas beaucoup des index (... selon "On m'a dit par ce mec que je connais")
jcolebrand
5
@jcolebrand: les vues en général sont grandement aidées par les index, selon la façon dont ils sont utilisés. Essentiellement, lorsqu'ils sont utilisés dans une requête donnée, ils bénéficieront comme si leur code était inséré directement dans la requête. Pour les vues et requêtes simples, cela signifie qu'ils utilisent des index aussi bien que n'importe quelle requête simple. Pour les vues / requêtes plus complexes, cela dépend de la capacité du planificateur de requêtes à réorganiser et à optimiser le travail à effectuer. La meilleure façon de voir cela est de choisir un grand ensemble de données et de fabriquer des exemples de vues et de requêtes en les utilisant, et de voir ce que le plan de requête SSMS indique que le QP fait avec eux.
David Spillett
6

En plus de ce que d'autres ont dit (clause WHERE, INDEX qui pourraient aider), je suggère que vous souhaitiez peut-être envisager des vues indexées - en supposant qu'il est même possible de créer des index sur la vue ( détails ). Ensuite, vous pourrez peut-être également appliquer l'indice NOEXPAND dans vos requêtes ( détails ).

AndrewSQL
la source
Ces détails semblent prometteurs. Laissez-moi les essayer et je reviendrai sur les résultats.
balu
4

La réponse générique est de jeter un œil au plan d'exécution. Vos jointures sont-elles indexées? Vos champs de sortie sont-ils inclus dans ces index? Produisez-vous uniquement les colonnes que vous devez voir?

Matt M
la source
0

Ce que je ferais probablement, c'est juste de créer 2 vues

  • La 1ère vue n'est que les champs que je dois rechercher; juste ces champs. Je retournerais le champ ID pour chaque ligne, plus le type de table que vous recherchez. J'ai fait une chose similaire en créant une vue UNION ALL qui a recherché plusieurs tables. Je viens de m'assurer d'inclure l'ID, le type et les champs de texte, je voulais rechercher.

  • La 2e vue gérerait l'affichage des résultats rassemblés dans la 1ère vue, et aurait chaque table dont vous avez besoin pour afficher les résultats, ou peut-être au lieu d'une vue, en faire une procédure stockée.

Je ferais un UNION ALL, avec un GROUP BY en bas, et je ne ferais pas tous ces JOINTS GAUCHE EXTÉRIEURS.

crosenblum
la source