2014-01-24 26 views
2

我有以下查詢:理解包括對指數

USE [AxReports] 
GO 

DECLARE @paramCompany varchar(3) 
SET @paramCompany = 'adf' 

SELECT stl.MAINSALESID, 
     st.DATAAREAID, 
     Sum(sl.SALESQTY) as 'Quantity', 
     Sum(sl.SALESQTY * sl.SALESPRICE) as 'SalesValue' 
INTO #openrel 
FROM 
    DynamicsV5Realtime.dbo.SALESTABLE st 
INNER JOIN 
    DynamicsV5Realtime.dbo.SALESLINE sl 
ON 
    sl.SALESID = st.SALESID 
    and sl.DATAAREAID = st.DATAAREAID 
INNER JOIN 
    DynamicsV5Realtime.dbo.INVENTTABLE it 
ON 
    it.ITEMID = sl.ITEMID 
    and it.DATAAREAID = sl.DATAAREAID 
INNER JOIN 
    DynamicsV5Realtime.dbo.SALESTABLELINKS stl 
ON 
    stl.SUBSALESID = st.SALESID 
    and stl.DATAAREAID = st.DATAAREAID 
WHERE 
    st.DATAAREAID = @paramCompany 
    and st.SALESTYPE = 3 -- Release Order 
    and st.SALESSTATUS = 1 
    and sl.SALESSTATUS <> 4 
    and it.ITEMGROUPID <> 'G0022A' 
GROUP BY 
    stl.MAINSALESID, 
    st.DATAAREAID 

我的執行計劃建議的指標:

USE [DynamicsV5Realtime] 
GO 
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>] 
ON [dbo].[INVENTTABLE] ([DATAAREAID],[ITEMGROUPID]) 
INCLUDE ([ITEMID]) 
GO 

但是我已經在該表的索引,它類似於其計劃正在使用,但對其執行表掃描。目前的指數低於:

CREATE NONCLUSTERED INDEX [I_ITEMGROUPIDX] ON [dbo].[INVENTTABLE] 
(
[ITEMID] ASC, 
[DATAAREAID] ASC 
) 
INCLUDE ( [ITEMGROUPID]) 
GO 

我有一個瞭解,你應該只把東西作爲一個包含列時,你是不是困擾對他們在葉級進行排序(我認爲是正確的嗎?)。

在這種情況下,WHERE子句有它.ITEMGROUPID <>'G0022A'因此把它作爲一個關鍵列是有意義的,因爲它會更快地按順序尋找該列(我再次認爲我是對的那麼?)

然而,聯接怎麼樣,爲什麼它建議將ITEMID列作爲包含但不包含DATAAREAID列? ITEMID和DATAAREAID在這種情況下構成了PK,所以它是不需要對兩列進行排序,並且可能使用現有索引,但將ITEMGROUPID作爲關鍵柱是更好的解決方案,即添加新索引? (那件事情我可以測試我想)

感謝

回答

3

讓我們先考慮一下這個表,那就是我們只關注查詢中直接提到的那些部分。

執行查詢需要做到以下幾點:

  1. 查找所有行INVENTTABLEITEMGROUPID列等於「G0022A」。
  2. 在這些行中查找DATAAREAIDITEMID列的值,用於在SALESLINE中查找必需的行。

做第一部分的最佳索引是在ITEMGROUPID上有一個鍵,但沒有其他列。這樣一個關鍵字(我們現在將忽略包含的列)將啓用表掃描以僅查找相關行和那些行。

如果沒有這樣的索引,但是有一個索引將ITEMGROUPID作爲其中一列,那麼該索引可以用於表掃描,而不是相當有效。

現在,當我們考慮第二部分時,我們實際關心的唯一值是DATAAREAIDITEMID

如果包含那些字段,那麼它們可以在索引掃描中使用。

如果它們實際上是密鑰的一部分,或者其中一個是另一個,那麼該索引也可以用於這樣的索引掃描。

所以。在這一點上,只考慮那些方面,我們說,我們會考慮在這一點上,而忽略其他因素(索引大小,插入的費用等),則下列任一指標在這裏很有用:

CREATE NONCLUSTERED INDEX [someIndexName] 
ON [dbo].[INVENTTABLE] ([ITEMGROUPID],[DATAAREAID],[ITEMID]) 

CREATE NONCLUSTERED INDEX [someIndexName] 
ON [dbo].[INVENTTABLE] ([ITEMGROUPID]) 
INCLUDE ([DATAAREAID],[ITEMID]) 

CREATE NONCLUSTERED INDEX [someIndexName] 
ON [dbo].[INVENTTABLE] ([ITEMGROUPID]) 
INCLUDE ([ITEMID],[DATAAREAID]) 

CREATE NONCLUSTERED INDEX [someIndexName] 
ON [dbo].[INVENTTABLE] ([DATAAREAID],[ITEMGROUPID]) 
INCLUDE ([ITEMID]) 

CREATE NONCLUSTERED INDEX [someIndexName] 
ON [dbo].[INVENTTABLE] ([ITEMID],[ITEMGROUPID]) 
INCLUDE ([DATAAREAID]) 

CREATE NONCLUSTERED INDEX [someIndexName] 
ON [dbo].[INVENTTABLE] ([ITEMGROUPID],[DATAAREAID]) 
INCLUDE ([ITEMID]) 

CREATE NONCLUSTERED INDEX [someIndexName] 
ON [dbo].[INVENTTABLE] ([ITEMGROUPID],[ITEMID]) 
INCLUDE ([DATAAREAID]) 

這些索引中的每一個都包含ITEMGROUPID作爲密鑰的全部或一部分,並且ITEMIDDATAAREAID作爲密鑰的一部分或包含在列中。

請注意,他們索引你確實與此相反;它具有理想的列作爲包含列的鍵,其他列作爲鍵的一部分。這比沒有好,查詢計劃人員可以重新調整東西來利用它,但它不是我們確定我們想要的東西的理想關鍵。

現在,讓我們將查詢視爲一個整體。

  1. 請注意,我們將根據DATAAREAID列搜索SALESTABLE列。
  2. 請注意,SALESLINE在其自己的DATAAREAID列中加入該列。
  3. 請注意,INVENTTABLE依次基於其自己的DATAAREAID列加入到該列的SALESLINE列。

由此我們可以推斷,我們在邏輯上只想要從INVENTTABLE那些在他們DATAAREAID列中的值@paramCompany這些記錄。

而規劃師做出了這個扣除。

因此,考慮到查詢作爲一個整體,我們可以改變上面我們兩個動作:

  1. 查找INVENTTABLE所有行ITEMGROUPID列等於「G0022A」何DATAAREAID等於@paramCompany
  2. 查找這些行中的DATAAREAID(已在步驟1中獲得)和ITEMID列的值。

因此,對於這個理想的指標是,要麼:

CREATE NONCLUSTERED INDEX [someName] 
ON [dbo].[INVENTTABLE] ([ITEMGROUPID],[DATAAREAID]) 
INCLUDE ([ITEMID]) 
GO 

OR

CREATE NONCLUSTERED INDEX [someName] 
ON [dbo].[INVENTTABLE] ([DATAAREAID],[ITEMGROUPID]) 
INCLUDE ([ITEMID]) 
GO 

(或一個包含在關鍵的三個,但也有其他原因不能有一個很大的鑰匙,如果你不需要它)。

而第二個確實是你建議做的。

+0

很好的解釋我會盡力消化這一切,非常感謝 – Tom

0

這應該是很容易谷歌,但我要說的基本上只是所使用的列加入索引,包括回報列,以便有不需要在實際的表上進行查找(al包含在索引中)。 我會說建議可能會或多或少是可靠的,也許是由於數據不好或其他原因,不要盲目依賴它們。另外,我認爲當運營商'<>'時不能使用索引。

+0

他們問爲什麼'DATAAREAID'是關鍵的一部分,而不是僅僅包含在內,這是人們從你的答案中可以期待的。 –