2012-07-12 5 views
0

J'ai une table de contrats qui est grande et que nous avons beaucoup de procédures stockées qui recherchent des contrats avec un statut de Ouvrir. Moins de 10% des contrats sont ouverts et ce nombre diminue à mesure que la BD se développe. J'ai pensé que je pourrais créer une vue indexée des contrats ouverts afin d'accélérer certaines de nos requêtes. Le problème est que l'état n'est pas sur la table de contrat et j'ai besoin d'une sous-requête pour récupérer les données que je veux. (SQL Server ne puis une analyse d'index ordonné en clusters sur la table l'ensemble des questions que je l'ai regardé)Vue indexée de SQL Server 2000 avec sous-requête max

Voici la version condensée de la vue (je l'ai enlevé les 30 autres colonnes de la table des contrats)

SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 

CREATE VIEW [dbo].[vw_OpenContractsIndexed] 
WITH SCHEMABINDING 
AS 
SELECT  c.ContractID 
FROM   dbo.NMPT_Contract AS c INNER JOIN 
         dbo.NMPT_ContractStatus AS cs ON c.ContractID = cs.ContractID AND cs.ContractStatusCreated = 
          (SELECT  MAX(ContractStatusCreated) AS Expr1 
          FROM   dbo.NMPT_ContractStatus AS cs2 
          WHERE  (ContractID = c.ContractID)) INNER JOIN 
         dbo.CMSS_Status AS s ON cs.StatusID = s.StatusID 
WHERE  (s.StatusCode = 'OPN') 

Si je tente de créer un index sur la vue (cluster unique sur contractid) Je reçois le texte suivant

Échec de création pour l'index
Il contient un ou plusieurs constructions non autorisées. (Microsoft SQL Server, erreur 1936)

De ce que je peux rassembler c'est le Max dans la sous-requête qui est le problème ??

En plus de mettre le statut sur la table de contrats (où je pense personnellement qu'il appartient) sont là des suggestions pour optimiser cette situation. A défaut, d'autres versions de SQL Server autoriseront-elles cette vue indexée?

Répondre

3

From TechNet regarding Indexed Views in SS 2000:

Il y a plusieurs restrictions sur la syntaxe de la définition de la vue. La définition de la vue ne doit pas contenir les éléments suivants:

COUNT (*)

fonction ROWSET

tableau dérivé

autojointure

DISTINCT

ECARTYPE, ÉCART, AVG

flotteur *, texte, ntext, colonnes d'image

sous-requête

prédicats texte intégral (CONTIENNENT, FREETEXT)

SUM sur l'expression annulable

MIN, MAX

TOP

OUTER rejoindre

UNION

Vous utilisez MAX et une sous-requête, les deux ne sont pas autorisés.

Pour obtenir des conseils sur la façon de contourner le problème, vous devez partager quelques données et ce que vous essayez de faire.

+0

Si le statusID était sur le contrat je l'indexerais et serait fait avec lui. En l'état, nous avons la même sous-requête dans de nombreuses procédures stockées et la base de données est obligée de déterminer continuellement l'état actuel du contrat. La plupart du temps, nous recherchons des contrats avec un statut actuel d'OPN. Y a-t-il un moyen d'optimiser cela? – PatFromCanada

+0

Plus One pour confirmer le problème avec la vue – PatFromCanada

1

Il ne s'agit pas d'une solution "Vue" et il faudra plus de travail à accomplir, mais vous pouvez créer une table dénormalisée qui contiendra le résultat de la vue. De cette façon, toutes les lectures pour les contrats Open peuvent aller à l'encontre de cette table. Ce sera le plus rapide, mais nécessitera la maintenance de la nouvelle table.

0

La création d'une vue indexée est une tâche difficile car elle a beaucoup de restitutions et une autre est liée à la jointure automatique. Vous avez auto se joindre ici.Aucune autre vue

Autre chose pour ce genre de tables principales si vous utilisez un seul statut comme 'OUVRIR' dans votre cas, je suggère que plutôt que de rejoindre la table (table principale avec le code d'état) déclarez simplement la variable statusid puis stockez la valeur pour le statut OPEN là et ensuite utilisez cette valeur dans la requête finale. Cela évitera une jointure supplémentaire avec une table principale.

Je suggère que vous stockez les données pour l'état ouvert dans la table temporaire avant de rejoindre la table de contrat dans l'instruction finale. Vous pouvez avoir un index sur statusid, customerid et contractcreationdate. Ensuite, la force de cet indice pour obtenir le contractId dans une table temporaire comme

select contractid into #temp from NMPT_ContractStatus 
where statusid [email protected] group by contractid   
having  datefield = max(datefield) 

maintenant se joindre à cette table temporaire avec la table du contrat.

Mais avant de créer un type d'index, assurez-vous que les frais généraux sont bien inférieurs aux avantages que vous obtenez.