2012-11-16 54 views
3

爲什麼SQL Server 2005會發現它更有效地執行表掃描,而不是使用主鍵(和主鍵)上的可用聚簇索引?在刪除語句上忽略聚集並覆蓋索引。發生表掃描

聲明: 有在主鍵不包括列的非聚集的,非唯一索引。這讓我感到莫名其妙,我們已經有了一個很好的辦公室笑容。如果這個指數最終成爲問題,那麼我們知道應該拍攝誰。不幸的是,這是一個生產網站,我不能把它撕掉,但是如果有必要,我們會制定計劃。

也許問題不是智力缺損相反指數,但是......

根據霧燈通過下列語句已在表上造成了掃描,約10萬行一個小時,當我們大約600倍通過主鍵刪除行:

DELETE FROM SomeBigTable WHERE ID = @ID 

表DDL:詳細

CREATE TABLE [SomeBigTable] 
(
    [ID] [int] NOT NULL, 
    [FullTextIndexTime] [timestamp] NOT NULL, 
    [FullTextSearchText] [varchar] (max) NOT NULL, 
    CONSTRAINT [PK_ID] PRIMARY KEY CLUSTERED 
    (
     [ID] ASC 
    ) 
) -- ... 
ON PRIMARY 

聚集索引約束:

ADD CONSTRAINT [PK_ID] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
) WITH PAD_INDEX = OFF 
     ,STATISTICS_NORECOMPUTE = OFF 
     ,SORT_IN_TEMPDB = OFF 
     ,IGNORE_DUP_KEY = OFF 
     ,ONLINE = OFF 
     ,ALLOW_ROW_LOCKS = ON 
     ,ALLOW_PAGE_LOCKS = ON 
     ,FILLFACTOR = 75 
ON PRIMARY 

在同一表上的非唯一的,非聚集索引:

CREATE NONCLUSTERED INDEX [IX_SomeBigTable_ID] ON [SomeBigTable] 
(
    [ID] ASC 
) WITH PAD_INDEX = OFF 
     ,STATISTICS_NORECOMPUTE = OFF 
     ,SORT_IN_TEMPDB = OFF 
     ,IGNORE_DUP_KEY = OFF 
     ,ONLINE = OFF 
     ,ALLOW_ROW_LOCKS = ON 
     ,ALLOW_PAGE_LOCKS = ON 
     ,FILLFACTOR = 98 
ON PRIMARY 

對[ID]列指向外鍵約束到一個同樣大的表。

使用相同的語句,600個表掃描約佔該表每小時總刪除操作的約4%。所以,並不是所有這個語句的執行都會導致表掃描。

不言而喻,但無論如何說...這是我想發送包裝很多討厭的I/O。

+0

是sql服務器掃描聚集索引還是非聚集索引? –

+0

也沒有。它正在掃描桌子。 – royalt

+0

我不認爲sql應該永遠不要做表掃描,只要表上有一個聚集索引。它應該掃描聚集索引。也許有人放棄了聚集索引並將表格變成了堆? –

回答

1

您是否嘗試過在表格上重新計算statistics並清除您的proc cache? 例如是這樣的:

USE myDatabase; 
GO 

UPDATE STATISTICS SomeBigTable; 
GO 

DBCC FREEPROCCACHE 
DBCC DROPCLEANBUFFERS 

這可能是SQL Server的只是使用了錯誤的指標,因爲它已經從當時有表中的不同數據緩存不錯的計劃。

+0

統計數據在發現問題前2天重新計算。我繼續前進並手動更新它們,看看我能否成功地實現它。我可以安排與客戶清除proc緩存,以查看行爲是否改變。但是,我對proc緩存的瞭解是,由於這些刪除語句的活動,其他語句正在刷新。 – royalt

1

有些事情要嘗試,有些事情要檢查:

你運行一個DELETE SomBigTable where ID = @Parameter聲明?如果是這樣,是@Parameter類型的int,或者它是一個不同的數據類型比被刪除的列? (也許不是,但我打一次,其中一個字符串是越來越澆鑄爲統一的情況,並導致索引被忽略。)

使數據庫和食堂周圍的副本與它:

  • 嘗試確定哪些刪除導致掃描,哪些不刪除
  • 它與FK相關表中是否存在數據有關?
  • 外鍵是否可信(通過sys.foriegn_keys檢查)
  • 拖放FK。它會改變什麼嗎?
  • 刪除第二個索引。這會改變什麼嗎?

可能是沒有這些,但是當他們瞎搞會碰上真正的問題絆倒。

+0

如果您無法獲得實時數據的副本,請使用(或製作)虛擬/測試數據。 –

+0

@Parameter實際上是一個INT,因爲它被傳遞給執行刪除的存儲過程。那裏沒什麼時髦的。好東西雖然檢查。你是否想要在刪除語句中排除FROM?聲明完全如上。我將模擬一些數據,因爲它需要幾個星期才能從客戶那裏檢索300 + GB數據庫進行測試。所有的子彈在測試和外鍵方面都很出色。 – royalt

+1

在T-SQL中,在DELETE語句中,「from」(如'FROM DELETE from MyTable ...')是可選的,所以懶惰,我不打擾它的輸入。 –