2

我有一個名爲tbl_event與非聚集索引IDX_Event_FolderIDX_Event_Time定義爲數據庫表一直沒有出現執行計劃顯示的正下方:的SQL Server非聚集索引在執行計劃

查詢1:

SELECT * 
FROM tbl_event 
WHERE tbl_event.nobjectid = 1410000 
ORDER BY tetime 

Execution Plan for Query 1

查詢2:

SELECT * 
FROM tbl_event 
WHERE tbl_event.nobjectid = 1410000 

Execution Plan for Query 2

我的問題是,爲什麼從來沒有利用上nobjectid指數?我希望在這些select語句的where子句中指定了nobjectid時,會有索引查找或掃描。我對這種分析的理解是不正確的?

+0

您可以發表包括(!)主鍵定義在內的表定義嗎? – TomTom 2011-02-09 18:20:59

+0

表中有多少行?有多少人的價值是`1410000`? – 2011-02-09 18:26:34

+0

18325170行當前在表中,其中只有大約30個有nobjectid = 1410000 – 2011-02-09 20:09:36

回答

2

您在評論中說,目前有在表18325170行,只有大約30人已經nobjectid = 1410000。

即使您的IDX_Event_Folder索引被禁用,我也不能相信SQL Server會爲這一行數量選擇此計劃,並且行厚度表示它認爲它處理的可能是1行而不是18325170!

Plan

所以我敢肯定,你必須有自動更新統計禁用?如果是這樣,您將需要手動更新統計信息(或者最好啓用此選項)

3

爲什麼nobjectid上的索引從不使用 ?我希望那裏是 索引查找或掃描指定nobjectid 當where子句

一個常見的誤解了!

有一點是:因爲您使用的是SELECT *,您需要表中的所有數據。所以最終,SQL Server必須返回到實際的數據頁面並獲取所有值。

當發生索引查找並發現命中時,在這種情況下,SQL Server必須執行書籤查找 - 這是一個相當昂貴的操作。

由於這些操作相當昂貴,所以如果可能的話,SQL Server會盡量避免它們 - 因此在很多情況下,將使用表掃描,因爲最終這比查找nc索引要快,然後做一個書籤查找。

點檢查:

  • 如何選擇性nobjectid列?這裏的這個聽起來像是一個或多或少的獨一無二的ID--那會很好。如果你碰巧在列上有一個索引,這個索引不是很有選擇性,那麼查詢優化器通常會忽略它(因爲它必須檢查太多的行,所以表掃描最後更快)

  • 有多少是否在表中?對小的表(少於幾千行),它往往要快得多做一個表掃描,從一開始走

而且,從與「RID堆查找」你的第一個執行計劃,我會總結你在桌子上沒有聚集索引 - 立即添加一個!沒有羣集密鑰(因此具有而不是聚簇表)也減慢了大量操作並降低了非聚集索引的有效性。

嘗試在 「NUSE」 列中添加您的聚集索引:

  • 獨特
  • 穩定
  • 不斷增加

INT IDENTITY是一個完美的候選人 - UNIQUEIDENTIFIER或者非常寬的一組色譜柱是最差的。閱讀所有關於Kimberly Tripp's blog

1

選擇聚集索引有一些重疊的事情在進行

  • SELECT *意思是「給我所有列」。優化器決定它掃描表格更有用。
  • 唯一有用的索引是訂購的時間。它這樣做,然後鑽到桌子上。
  • 您沒有聚簇索引(RID /堆查找顯示)
  • nobjectid索引缺乏唯一性將無濟於事:它意味着完整的索引掃描。 o爲什麼在結合SELECT *時使用索引?

如果你有這一點,那麼該指數將使用(如掃描)

SELECT nobjectid 
FROM tbl_event 
WHERE tbl_event.nobjectid = 1410000 

或者這一點,新指數將最有可能被使用

CREATE NONCLUSTERED INDEX [IDX_Co,bined] 
ON [dbo].[tbl_event]([nobjectid] ASC, tetime) 

SELECT nobjectid, tetime 
FROM tbl_event 
WHERE tbl_nobjectid = 1410000 
ORDER BY tetime 

我建議你閱讀這些文章

缺乏聚集索引應該由這些文章中介紹過