Bazı sorguları optimize etmeye çalışıyorum.
Aşağıdaki sorgu için,
SET STATISTICS IO ON;
DECLARE @OrderStartDate DATETIME2 = '27 feb 2016';
DECLARE @OrderEndDate DATETIME2 = '28 feb 2016';
SELECT o.strBxOrderNo
, o.sintOrderStatusID
, o.sintOrderChannelID
, o.sintOrderTypeID
, o.sdtmOrdCreated
, o.sintMarketID
, o.strOrderKey
, o.strOfferCode
, o.strCurrencyCode
, o.decBCShipFullPrice
, o.decBCShipFinal
, o.decBCShipTax
, o.decBCTotalAmount
, o.decWrittenTotalAmount
, o.decBCWrittenTotalAmount
, o.decBCShipOfferDisc
, o.decBCShipOverride
, o.decTotalAmount
, o.decShipTax
, o.decShipFinal
, o.decShipOverride
, o.decShipOfferDisc
, o.decShipFullPrice
, o.lngAccountParticipantID
, CONVERT(DATE, o.sdtmOrdCreated, 120) as OrderCreatedDateConverted
FROM tablebackups.dbo.tblBOrder o
WHERE o.sdtmOrdCreated >= @OrderStartDate
AND o.sdtmOrdCreated < @OrderEndDate
AND EXISTS (
SELECT *
FROM tablebackups.dbo.tblBOrderItem oi
WHERE oi.strBxOrderNo = o.strBxOrderNo
AND oi.decCatItemPrice > 0
)
OPTION (RECOMPILE);
Aşağıdaki FILTERED dizinini oluşturdum:
-- table dbo.tblBorderItem
CREATE NONCLUSTERED INDEX IX_tblBOrderItem_decCatItemPrice_INCL
ON dbo.tblBorderItem
(
strBxOrderNo ASC
, sintOrderSeqNo ASC
, decCatItemPrice
)
INCLUDE
(
blnChargeShipping
, decBCCatItemPrice
, decBCCostPrice
, decBCFinalPrice
, decBCOfferDiscount
, decBCOverrideDiscount
, decBCTaxAmount
, decCostPrice
, decFinalPrice
, decOfferDiscount
, decOverrideDiscount
, decTaxAmount
, decWasPrice
, dtmOrdItemCreated
, sintOrderItemStatusId
, sintOrderItemType
, sintQuantity
, strItemNo
)
WHERE decCatItemPrice > 0
WITH (DROP_EXISTING = ON, FILLFACTOR = 95);
Bu dizin yalnızca bu sorgu için kullanılmaz, aynı dizini kullanan başka sorgular, dolayısıyla DAHİL sütunlar da vardır.
Özellikle bu sorgu için, sadece bir siparişin herhangi bir öğeye sahip olup olmadığını kontrol etmek istiyorum (EXISTS) decCatItemPrice > 0
.
SQL Server, aşağıdaki resimlerde gördüğünüz gibi bir dizin taraması yapıyor.
- İstatistikler güncellendi.
- Kalem tablosunda test edilen 41.208 satır vardır.
Unutmayın, öğeler tablosundan sütun seçmiyorum.
Bu kalem tablo canlı olarak 164.309.397 adet var. Orada bir tarama yapmaktan kaçınmak istiyorum.
sorular:
SQL Server neden dizin araması yapmıyor?
Bu sorguyu geliştirmek için dikkate almam gereken başka faktörler / şeyler var mı?
(4537 row(s) affected) Table 'tblBorder'. Scan count 1, logical reads
116, physical reads 0, read-ahead reads 0, lob logical reads 0, lob
physical reads 0, lob read-ahead reads 0. Table 'tblBorderItem'. Scan
count 1, logical reads 689, physical reads 0, read-ahead reads 0, lob
logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row(s) affected)
tblBorderItem tablosundaki tanım ve dizinler budur
IF OBJECT_ID('[dbo].[tblBorderItem]') IS NOT NULL
DROP TABLE [dbo].[tblBorderItem]
GO
CREATE TABLE [dbo].[tblBorderItem] (
[strBxOrderNo] VARCHAR(20) NOT NULL,
[sintOrderSeqNo] SMALLINT NOT NULL,
[sintOrderItemStatusId] SMALLINT NOT NULL,
[sintNameStructureID] SMALLINT NOT NULL,
[strItemNo] VARCHAR(20) NOT NULL,
[sintQuantity] SMALLINT NOT NULL,
[strCurrencyCode] VARCHAR(3) NOT NULL,
[decCostPrice] DECIMAL(18,4) NOT NULL,
[decCatItemPrice] DECIMAL(18,2) NOT NULL,
[decOfferDiscount] DECIMAL(18,2) NOT NULL,
[decOverrideDiscount] DECIMAL(18,2) NOT NULL,
[decFinalPrice] DECIMAL(18,2) NOT NULL,
[decTaxAmount] DECIMAL(18,2) NOT NULL,
[strBCCurrencyCode] VARCHAR(3) NOT NULL,
[decBCCostPrice] DECIMAL(18,4) NOT NULL,
[decBCCatItemPrice] DECIMAL(18,4) NOT NULL,
[decBCOfferDiscount] DECIMAL(18,4) NOT NULL,
[decBCOverrideDiscount] DECIMAL(18,4) NOT NULL,
[decBCFinalPrice] DECIMAL(18,4) NOT NULL,
[decBCTaxAmount] DECIMAL(18,4) NOT NULL,
[dtmOrdItemCreated] DATETIME NOT NULL,
[blnChargeShipping] BIT NOT NULL,
[lngTimeOfOrderQtyOnHand] INT NULL,
[sdtmTimeOfOrderDueDate] SMALLDATETIME NULL,
[lngProdSetSeqNo] INT NULL,
[lngProdRelationId] INT NULL,
[lngProdRelationMemberId] INT NULL,
[decWasPrice] DECIMAL(18,2) NULL,
[sintOrderItemType] SMALLINT NULL,
[tsRowVersion] TIMESTAMP NULL,
[sdtmOrderItemStatusUpdated] SMALLDATETIME NULL,
CONSTRAINT [PK_tblBOrderItem]
PRIMARY KEY CLUSTERED
([strBxOrderNo] asc, [sintOrderSeqNo] asc)
WITH FILLFACTOR = 100)
GO
CREATE NONCLUSTERED INDEX
[IX_tblBOrderItem__dtmOrdItemCreated]
ON [dbo].[tblBorderItem] ([dtmOrdItemCreated] asc)
WITH FILLFACTOR = 100
CREATE NONCLUSTERED INDEX [IX_tblBOrderItem__sintOrderItemStatusId]
ON [dbo].[tblBorderItem] ([sintOrderItemStatusId] asc)
INCLUDE ([sdtmOrderItemStatusUpdated],
[sintOrderSeqNo], [strBxOrderNo], [strItemNo])
WITH FILLFACTOR = 100
CREATE NONCLUSTERED INDEX [IX_tblBOrderItem__
sintOrderItemStatusId_decFinalPrice_
sdtmOrderItemStatusUpdated_
include_strBxOrderNo]
ON [dbo].[tblBorderItem]
([sintOrderItemStatusId] asc,
[decFinalPrice] asc,
[sdtmOrderItemStatusUpdated] asc)
INCLUDE ([strBxOrderNo])
WITH FILLFACTOR = 100
CREATE NONCLUSTERED INDEX [IX_tblBOrderItem__strBxOrderNo]
ON [dbo].[tblBorderItem]
([strBxOrderNo] asc)
WITH FILLFACTOR = 100
CREATE NONCLUSTERED INDEX [IX_tblBOrderItem__strItemNo]
ON [dbo].[tblBorderItem] ([strItemNo] asc)
WITH FILLFACTOR = 100
CREATE NONCLUSTERED INDEX
[IX_tblBOrderItem_decCatItemPrice_INCL]
ON [dbo].[tblBorderItem]
([strBxOrderNo] asc, [sintOrderSeqNo] asc, [decCatItemPrice] asc)
INCLUDE ([blnChargeShipping],
[decBCCatItemPrice], [decBCCostPrice], [decBCFinalPrice],
[decBCOfferDiscount], [decBCOverrideDiscount],
[decBCTaxAmount], [decCostPrice], [decFinalPrice],
[decOfferDiscount], [decOverrideDiscount],
[decTaxAmount], [decWasPrice], [dtmOrdItemCreated],
[sintOrderItemStatusId], [sintOrderItemType],
[sintQuantity], [strItemNo])
WHERE ([decCatItemPrice]>(0))
WITH FILLFACTOR = 95
tblBorder tablosundaki tanım ve dizinler budur
IF OBJECT_ID('[dbo].[tblBorder]') IS NOT NULL
DROP TABLE [dbo].[tblBorder]
GO
CREATE TABLE [dbo].[tblBorder] (
[strBxOrderNo] VARCHAR(20) NOT NULL,
[uidOrderUniqueID] UNIQUEIDENTIFIER NOT NULL,
[sintOrderStatusID] SMALLINT NOT NULL,
[sintOrderChannelID] SMALLINT NOT NULL,
[sintOrderTypeID] SMALLINT NOT NULL,
[blnIsBasket] BIT NOT NULL,
[sdtmOrdCreated] SMALLDATETIME NOT NULL,
[sintMarketID] SMALLINT NOT NULL,
[strOrderKey] VARCHAR(20) NOT NULL,
[strOfferCode] VARCHAR(20) NOT NULL,
[lngShippedToParticipantID] INT NOT NULL,
[lngOrderedByParticipantID] INT NOT NULL,
[lngShipToAddressID] INT NOT NULL,
[lngAccountAddressID] INT NOT NULL,
[lngAccountParticipantID] INT NOT NULL,
[lngOrderedByAddressID] INT NOT NULL,
[lngOrderTakenBy] INT NOT NULL,
[strCurrencyCode] VARCHAR(3) NOT NULL,
[decShipFullPrice] DECIMAL(18,2) NOT NULL,
[decShipOfferDisc] DECIMAL(18,2) NOT NULL,
[decShipOverride] DECIMAL(18,2) NOT NULL,
[decShipFinal] DECIMAL(18,2) NOT NULL,
[decShipTax] DECIMAL(18,2) NOT NULL,
[strBCCurrencyCode] VARCHAR(3) NOT NULL,
[decBCShipFullPrice] DECIMAL(18,4) NOT NULL,
[decBCShipOfferDisc] DECIMAL(18,4) NOT NULL,
[decBCShipOverride] DECIMAL(18,4) NOT NULL,
[decBCShipFinal] DECIMAL(18,4) NOT NULL,
[decBCShipTax] DECIMAL(18,4) NOT NULL,
[decTotalAmount] DECIMAL(18,2) NOT NULL,
[decBCTotalAmount] DECIMAL(18,4) NOT NULL,
[decWrittenTotalAmount] DECIMAL(18,2) NULL,
[decBCWrittenTotalAmount] DECIMAL(18,4) NULL,
[blnProRataShipping] BIT NOT NULL,
[blnChargeWithFirstShipment] BIT NOT NULL,
[sintShippingServiceLevelID] SMALLINT NOT NULL,
[sintShippingMethodID] SMALLINT NOT NULL,
[sdtmDoNotShipUntil] SMALLDATETIME NULL,
[blnHoldUntilComplete] BIT NOT NULL,
[tsRowVersion] TIMESTAMP NULL,
CONSTRAINT [PK_tblBOrder]
PRIMARY KEY CLUSTERED
([strBxOrderNo] asc) WITH FILLFACTOR = 100)
GO
CREATE NONCLUSTERED INDEX
[IX_tblBOrder__lngAccountAddressID]
ON [dbo].[tblBorder]
([lngAccountAddressID] asc, [sintOrderStatusID] asc)
WITH FILLFACTOR = 100
CREATE NONCLUSTERED INDEX
[IX_tblBOrder__lngAccountParticipantID]
ON [dbo].[tblBorder]
([lngAccountParticipantID] asc)
WITH FILLFACTOR = 100
CREATE NONCLUSTERED INDEX
[IX_tblBOrder__lngOrderedByAddressID]
ON [dbo].[tblBorder]
([lngOrderedByAddressID] asc, [sintOrderStatusID] asc)
WITH FILLFACTOR = 100
CREATE NONCLUSTERED INDEX
[IX_tblBOrder__lngOrderedByParticipantID]
ON [dbo].[tblBorder] ([lngOrderedByParticipantID] asc)
WITH FILLFACTOR = 100
CREATE NONCLUSTERED INDEX
[IX_tblBOrder__lngShippedToParticipantID]
ON [dbo].[tblBorder]
([lngShippedToParticipantID] asc)
WITH FILLFACTOR = 100
CREATE NONCLUSTERED INDEX
[IX_tblBOrder__lngShipToAddressID]
ON [dbo].[tblBorder]
([lngShipToAddressID] asc, [sintOrderStatusID] asc)
WITH FILLFACTOR = 100
CREATE NONCLUSTERED INDEX
[IX_tblBOrder__sdtmOrdCreated_sintMarketID__include_strBxOrderNo]
ON [dbo].[tblBorder]
([sdtmOrdCreated] asc, [sintMarketID] asc)
INCLUDE ([strBxOrderNo])
WITH FILLFACTOR = 100
CREATE NONCLUSTERED INDEX
[IX_tblBOrder_sdtmOrdCreated_INCL]
ON [dbo].[tblBorder]
([sdtmOrdCreated] asc)
INCLUDE ([decBCShipFinal], [decBCShipFullPrice],
[decBCShipOfferDisc], [decBCShipOverride],
[decBCShipTax], [decBCTotalAmount], [decBCWrittenTotalAmount],
[decShipFinal], [decShipFullPrice], [decShipOfferDisc],
[decShipOverride], [decShipTax], [decTotalAmount],
[decWrittenTotalAmount], [lngAccountParticipantID],
[lngOrderedByParticipantID], [sintMarketID],
[sintOrderChannelID], [sintOrderStatusID],
[sintOrderTypeID], [strBxOrderNo], [strCurrencyCode],
[strOfferCode], [strOrderKey])
WITH FILLFACTOR = 100
CREATE NONCLUSTERED
INDEX [IX_tblBOrder_sintMarketID_sdtmOrdCreated]
ON [dbo].[tblBorder]
([sintMarketID] asc, [sdtmOrdCreated] asc)
INCLUDE ([sintOrderChannelID], [strBxOrderNo])
WITH FILLFACTOR = 100
CREATE NONCLUSTERED
INDEX [IX_tblBOrder__sintOrderChannelID_sdtmOrdCreated_INCL]
ON [dbo].[tblBorder]
([sintOrderChannelID] asc, [sdtmOrdCreated] asc)
INCLUDE ([decBCShipFinal], [decBCShipFullPrice],
[decBCShipTax], [decShipFinal], [decShipFullPrice],
[decShipTax], [lngAccountParticipantID], [sintMarketID],
[sintOrderTypeID], [strBxOrderNo],
[strCurrencyCode], [strOrderKey])
WITH FILLFACTOR = 100
CREATE NONCLUSTERED INDEX [IX_tblBOrder_strBxOrderNo_sdtmOrdCreated_incl]
ON [dbo].[tblBorder] ([strBxOrderNo] asc,
[sdtmOrdCreated] asc)
INCLUDE ([sintOrderChannelID], [sintOrderTypeID], [sintMarketID],
[strOrderKey], [lngAccountParticipantID], [strCurrencyCode],
[decShipFullPrice], [decShipFinal], [decShipTax],
[decBCShipFullPrice], [decBCShipFinal],
[decBCShipTax])
Sonuç
İndeksimi LIVE sistemine uyguladım ve saklı yordamımı SMALLDATETIME kullanacak şekilde güncelledim.
Bundan sonra, sorgu planına bakarken aşağıdaki resmi görüyorum:
tam olarak böyle olmasını istedim.
Bu durumda sorgu iyileştirici her iki ortamda da en iyi sorgu planı almak için iyi bir iş yaptığını düşünüyorum ve herhangi bir sorgu ipuçları eklemedim sevindim.
Gönderilen 3 cevapla öğrendim. cevapları için Max Vernon , Paul White ve Daniel Hutmacher'e teşekkürler .