複合非聚集索引——列順序重要麼?

来源:http://www.cnblogs.com/woodytu/archive/2016/06/28/5622870.html
-Advertisement-
Play Games

當我談論索引時,大家經常會問我在複合非聚集索引里,列的順序是否重要?簡單來說:“看情況”。我們來具體看下為啥“看情況”…… 單例查找(Singleton Lookups) 當在你的表上有進行單例查找的查詢時,在複合非聚集索引里列的順序真的不重要。假設下列查詢: 現在你可以在StateProvince ...


當我談論索引時,大家經常會問我在複合非聚集索引里,列的順序是否重要?簡單來說:“看情況”。我們來具體看下為啥“看情況”……

單例查找(Singleton Lookups)

當在你的表上有進行單例查找的查詢時,在複合非聚集索引里列的順序真的不重要。假設下列查詢:

-- Without a supporting Non-Clustered Index we have to scan the complete Clustered Index
SELECT AddressID FROM Person.Address
WHERE StateProvinceID = 79 AND City = 'Bothell'
GO

現在你可以在StateProvinceIDCity,或CityStateProvinceID創建非聚集索引:

-- Create a supporting Non-Clustered Index
CREATE NONCLUSTERED INDEX idx_Test ON Person.Address(StateProvinceID, City)
GO

-- SQL Server performs a Non-Clustered Index Seek operation in combination with a Seek Predicate
SELECT AddressID FROM Person.Address
WHERE StateProvinceID = 79 AND City = 'Bothell'
GO

-- Change the column ordering
CREATE NONCLUSTERED INDEX idx_Test ON Person.Address(City, StateProvinceID)
WITH (DROP_EXISTING = ON)
GO

-- The column ordering doesn't matter in the Non-Clustered Index
SELECT AddressID FROM Person.Address
WHERE StateProvinceID = 79 AND City = 'Bothell'
GO

這裡非聚集索引里的列的順序真的不重要,因為SQL Server在執行計劃里直接進行非聚集索引查找操作(在與查找謂語集合里):

範圍掃描(Range Scans)

當我們討論在表上的範圍掃描時,這裡你檢索一組數據,就是另一回事了。假設你執行下列查詢:

SELECT AddressID FROM Person.Address
WHERE StateProvinceID BETWEEN 10 AND 12 AND City = 'Bothell'
GO

這次,支持的非聚集索引,你有2個方法:

  • StateProvinceID和City列上的非聚集索引
  • City和StateProvinceID列上的非聚集索引

我們先用第一個方法:

-- Create a supporting Non-Clustered Index
CREATE NONCLUSTERED INDEX idx_Test ON Person.Address(StateProvinceID, City)
GO

這個情況下,如你在執行計劃里所見,SQL在StateProvinceID列上對查詢進行非聚集索引查找操作,對於City列要計算剩餘謂語的值:

這真的不是個完美的執行計劃,因為你讀取了比你請求更多的數據。但有基於StateProvinceID列上的排序作為引導列, City作為隨後列,這是唯一可能的行為,如你從下圖所見:

現在我們嘗試交換下列來創建非聚集索引:City作為引導列,StateProvinceID作為第二列:

-- Change the column ordering in the Non-Clustered Index
CREATE NONCLUSTERED INDEX idx_Test ON Person.Address(City, StateProvinceID)
WITH (DROP_EXISTING = ON)
GO

-- Non-Clustered Index Seek on StateProvinceID *without* a Residual Predicate on column City
SELECT AddressID FROM Person.Address
WHERE StateProvinceID BETWEEN 10 AND 12 AND City = 'Bothell'
GO

當你再次執行你的查詢,你會看到SQL Server再次執行了非聚集索引查找操作。但這次對於你的查詢,“沒有”剩餘謂語(Residual Predicate)。

因為你物理上讀取的剛好是你邏輯上請求的數據。但這個現在這麼可能呢?那就看看下麵的圖:在非聚集索引里數據是如何排序的:

如你所見,現在的數據按City預先排,在每個City組裡,你會有在StateProvinceID列的排序。因此你可以直接獲得邏輯請求的數據——不用進一步剩餘謂語(Residual Predicate)的值計算就可以返回值。

小結

當你要進行範圍掃描時——在複合非聚集索引里列的順序重要的!在多次交流會上我經常提到:SQL Server里的一切幾戶都與索引有關,索引本身就會預排序數據!沒別的!理解SQL Server是否可以直接查找邏輯請求的數據,你也需要在你的心中想象下如何使如何預排序的,你如何通過有效預排序數據來訪問它。

希望這篇文章可以讓你更好的理解在非聚集索引里,列排序如何影響查找操作。

感謝關註!

原文鏈接

https://www.sqlpassion.at/archive/2016/06/27/composite-non-clustered-indexes-does-the-sorting-order-matter


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 介紹 作業也叫做事件調度,其實它也就是一個時間觸發器;它可以定義某個時間點執行指定的資料庫命令操作。 語法 CREATE [DEFINER = { user | CURRENT_USER }] ######定義創建人,預設創建事件的用戶就是事件的定義人,必須具備super許可權才能指定其他用戶。 EV ...
  • 一. 在sql server下處理需要導出的資料庫 1. 執行以下sql,查出所有'float'類型的欄位名,手動將float類型改為decimal(18,4). select 表名=d.name,欄位名=a.name,類型=b.name FROM syscolumns a left join sy ...
  • 本文為作者原創,轉載請註明原作者及轉載地址。 上一篇講瞭如何用thinkPHP框架實現數據的添加,那這一篇就講一下如何用thinkPHP實現數據的刪除和批量刪除吧。 預期效果圖: 原諒博主對照片的處理是如此的草率吧。。。 仍然是 通過MVC模式進行拆分: 首先是視圖部分: 仍然是採用表單傳值的方法, ...
  • http://www.postgresonline.com/journal/archives/131-Using-Recursive-Common-table-expressions-to-represent-Tree-structures.html Tree Problem and was bas ...
  • 幾個重要概念 Slab memcached通過slab機制進行記憶體的分配和回收,slab是一個記憶體塊,它是memcached一次申請記憶體的最小單位,。在啟動memcached的時候一般會使用參數-m指定其可用記憶體,但是並不是在啟動的那一刻所有的記憶體就全部分配出去了,只有在需要的時候才會去申請,而且每 ...
  • 本文轉自http://www.cnblogs.com/yunf/archive/2011/04/12/2013448.html,在此感謝作者yfProgramer。 對於我這種剛學mysql的,還是十分有用的。 雖然現在mysql已經可以利用workbench直接創建資料庫了,但是開頭的對庫和表的增 ...
  • 好久不寫文,最近得空寫一點。Oracle資料庫國內用戶量主要在企業上,其中有一種byte的存儲稱為Blob,並不能直接看。 有時候為了調試需要,可以通過: 這種sql去轉為字元串查看,但是不方便,一次最多轉出2000個位元組。需要通過index拼成完整的文本。 另外一種情況下,如果存儲的是圖片、wor ...
  • 安裝好MySQL以後,系統給了個預設的的密碼,然後說如果忘記了預設的密碼。。。。。。我複製了預設密碼就走過了只一步,這一步就是我漫長旅程的開始。他給的密碼太複雜了,當然我得換一個,而且我還要假裝我不記得密碼了,就這樣我走上了不歸路。。。。。。 這個過程是心酸的,網上的資料多如狗,關鍵是各有各的錯法, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...