web-dev-qa-db-fra.com

Comment optimiser: avoir compté (*)> 1

Sans envisager les index, existe-t-il un moyen de ré-écrire cette requête et d'obtenir le même résultat plus rapide?

select fo.OrderNo, fo.OrderItemSeqNo, COUNT(*)
from Facts.FactBackOrder fo
group by fo.OrderNo, fo.OrderItemSeqNo
having COUNT(*)>1

Quand je la réinscrit comme le suivant, il s'aggrave même.

;WITH R1 AS (

select ROW_NUMBER() OVER (PARTITION BY fo.OrderNo, fo.OrderItemSeqNo ORDER BY fo.OrderNo, fo.OrderItemSeqNo) AS N
       ,fo.OrderNo
       , fo.OrderItemSeqNo
from Facts.FactBackOrder fo
)

SELECT * FROM R1 WHERE N = 2

OU CA:

;WITH R1 AS (

select COUNT_BIG(*) OVER (PARTITION BY fo.OrderNo, fo.OrderItemSeqNo) AS N
       ,fo.OrderNo
       , fo.OrderItemSeqNo
from Facts.FactBackOrder fo
)

SELECT * FROM R1 WHERE N > 1

C'est une table de fait dans une datawarehouse. Les index sont sur l'image ci-dessous.

enter image description here

Une vue indexée dans cette situation utiliserait beaucoup moins d'espace qu'un indice. J'ai cette situation dans une vue indexée similaire - vous pouvez voir le code ci-dessous:

CREATE view [dbo].[VProcessStatus]
WITH SCHEMABINDING
AS
select processstatus, 
      StatusCount = COUNT_BIG(*) 
      FROM DBO.tbltaxtransaction
      GROUP BY processstatus
GO

GRANT SELECT ON [dbo].[VProcessStatus] TO [mydomain\itdevelopment] AS [dbo]
GO


CREATE UNIQUE CLUSTERED INDEX [IDX_VProcessStatus] ON [dbo].[VProcessStatus]
(
    [processstatus] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [pscheme_ProcessStatus]([processstatus])
GO

quand je cherche l'espace utilisé par cette vue et la table sous-jacente:

sp_spaceused 'tbltaxtransaction'
go
sp_spaceused 'VProcessStatus'
go

Je reçois le résultat suivant:

enter image description here

Le seul supplément est que cette vue indexée est partitionnée en fonction des fonctions de schéma de partition et de partition ci-dessous:

CREATE PARTITION SCHEME [pscheme_ProcessStatus] AS PARTITION [pfunc_ProcessStatus] TO ([FG01], [FG02], [FG03], [FG04], [FG05])
GO

CREATE PARTITION FUNCTION [pfunc_ProcessStatus](int) AS RANGE LEFT FOR VALUES (1, 2, 3, 9)
GO
4
Marcello Miorelli

J'ai maintenant quitté Dev à la production. Le fait de la table a 4 183 289 rangées.

SQL Server 2012. Microsoft SQL Server 2012 (SP1) - 11.0.3412.0 (x64) mars 2014 01:25:09 Copyright (c) Microsoft Corporation Enterprise Edition (64 bits) sur Windows NT 6.3 (Build 9600 :)

Mais je ne veux pas utiliser des index de colonne - ces tables sont mises à jour très souvent. Peut-être dans SQL 2014?

le plan de requête original de la requête que je voulais améliorer la performance de l'est:

enter image description here

la seule façon dont j'ai découvert l'amélioration de la requête orginale était d'ajouter un index à la table.

create index idx_FactBackOrder_OrderNo_OrderItemSeqNo 
on Facts.FactBackOrder (OrderNo,OrderItemSeqNo) with (online=on)

Quand j'exécute ensuite la requête, je remarque qu'il faut plus de temps que l'original sans index. Le nouveau plan de requête, après avoir créé l'index, est la suivante:

enter image description here

Je dépose immédiatement l'index nouvellement créé:

drop index idx_FactBackOrder_OrderNo_OrderItemSeqNo on Facts.FactBackOrder

Je crée ensuite une vue indexée:

--drop view [dbo].[VfactBackOder]

CREATE view [dbo].[VfactBackOder]
WITH SCHEMABINDING
AS
select fo.OrderNo, 
       fo.OrderItemSeqNo, 
       COUNT_BIG(*) as the_number
from Facts.FactBackOrder fo
group by fo.OrderNo, fo.OrderItemSeqNo
GO

créez l'index en cluster pour la vue indexée:

CREATE UNIQUE CLUSTERED INDEX [IDX_VfactBackOder] ON [dbo].[VfactBackOder]
(
    OrderNo, OrderItemSeqNo
)
go

Lorsque j'exécute la requête en utilisant la vue indexée nouvellement créée au lieu de la requête d'origine faisant référence aux tables sous-jacentes:

select fo.OrderNo, 
       fo.OrderItemSeqNo,
       fo.the_number
from VfactBackOder fo
where fo.the_number > 1

Je reçois un résultat non satisfaisant. Ensuite, j'ajoute un autre index à la vue:

CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[VfactBackOder] ([the_number])
INCLUDE ([OrderNo],[OrderItemSeqNo])
go

Maintenant, la requête vole comme une fusée. Le nouveau plan de requête est: enter image description here

Et regarder l'espace utilisé par la vue indexée et la table sous-jacente:

sP_SPACEUSE 'FACTSS.FACKBACKER' GO SP_SPACEUSEUSE "VFFFIQULTBODER" Go

enter image description here

la requête fonctionne assez bien, les clients heureux ici. Merci pour tous vos commentaires.

1
Marcello Miorelli