SQL Server 索引列的順序——真的沒關係嗎
問題:
當設定表的索引時,在效能上有一個微妙的平衡:太多的索引將影響你的INSERT/UPDATE/DELETE操作。但是索引不足又將影響你的SELECT操作。本文將著眼於索引的列順序和如何影響查詢計劃及效能。
解決方案:
示例SQLServer表和資料集:
-- Tablecreation logic
CREATE TABLE[dbo].[TABLE1]
([col1][int] NOT NULL,[col2] [int]NULL,[col3] [int] NULL,[col4][varchar](50)NULL)
GO
CREATE TABLE[dbo].[TABLE2]
([col1][int] NOT NULL,[col2] [int]NULL,[col3] [int] NULL,[col4][varchar](50)NULL)
GO
ALTER TABLEdbo.TABLE1ADD CONSTRAINT PK_TABLE1 PRIMARY KEY CLUSTERED (col1)
GO
ALTER TABLEdbo.TABLE2ADD CONSTRAINT PK_TABLE2 PRIMARY KEY CLUSTERED (col1)
GO
--Populate tables
DECLARE @val INT
SELECT @val=1
WHILE @val< 1000
BEGIN
INSERT INTO dbo.Table1(col1,col2, col3, col4)VALUES(@val,@val,@val,'TEST')
INSERT INTO dbo.Table2(col1,col2, col3, col4)VALUES(@val,@val,@val,'TEST')
SELECT @val=@val+1
END
GO
--Create multi-column index on table1
CREATE NONCLUSTEREDINDEX IX_TABLE1_col2col3ONdbo.TABLE1(col2,col3)
WITH (STATISTICS_NORECOMPUTE=OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS=ON, ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY]
GO
在執行下面的程式碼前請先開啟執行計劃(Ctrl+M)和開啟統計IO的語句:SET STATISTICS IO ON
單表查詢例子:
在第一個例子裡面,我們將使用在where子句中的一列來查詢。第一個查詢中where子句的索引使用第二列(col3),第二個查詢使用第一列(col2)。注意這裡使用了“DBCC DROPCLEANBUFFERS”,用於確保沒有快取帶來的影響,程式碼如下:
DBCC DROPCLEANBUFFERS
GO
SELECT * FROM dbo.TABLE1 WHEREcol3=88
GO
DBCC DROPCLEANBUFFERS
GO
SELECT * FROM dbo.TABLE1 WHEREcol2=88
GO
執行後檢視執行計劃如下:
可以看到,第一個查詢使用第二列(col3)的索引是在表上執行索引掃描,且沒有用到剛才建立的索引。第二個查詢使用了表查詢,使得在表裡只需要使用更少的資源。第一個查詢讀了6次,而第二個查詢只讀了4次。
執行查詢後,你應該大概猜到,當表越來越大的時候,效能優勢就顯現出來了。
兩表關聯查詢例子:
在下一個例子中,查詢使用同樣的where子句,但增加了一個inner join 關聯另外一個表。第一個查詢的where子句使用col3,並使用col2來關聯表。
第二個查詢的where子句使用col2,並使用col3來關聯表。
同樣,先執行DBCC DROPCLEANBUFFERS來確保快取已經清空。程式碼如下:
DBCC DROPCLEANBUFFERS
GO
SELECT *
FROM dbo.TABLE1 INNER JOIN
dbo.TABLE2 ON dbo.TABLE1.col2 = dbo.TABLE2.col1
WHERE dbo.TABLE1.col3=255
GO
DBCC DROPCLEANBUFFERS
GO
SELECT *
FROM dbo.TABLE1 INNER JOIN
dbo.TABLE2 ON dbo.TABLE1.col3 = dbo.TABLE2.col1
WHERE dbo.TABLE1.col2=255
GO
執行計劃如下:
從執行計劃可以看到,當用於關聯表的列也在索引中,但不是第一列時,會執行索引掃描。第二個查詢中索引的第一列來關列,會使用索引查詢。從IO來看,同樣索引查詢的讀次數會更小。
總結:
從這些例子中,可以看到索引列的順序對錶的查詢也有影響。當建立索引時,先確認你總是對儘可能小的集合進行操作,這意味著索引能從where子句中的列開始。另外,對order by子句中的列和SELECT中的列建立覆蓋索引也有助於提高查詢效能。這樣可以不用在查詢時執行書籤查詢。
在前面提到的,增加太多索引將引起insert/update/delete時對這些索引列的修改。所以,找到平衡點才是最重要的。
相關文章
- SQL Server SQL語句執行順序SQLServer
- 【Oracle】-【插入讀取順序】-插入讀取之間的順序關係Oracle
- 列定義的順序和列儲存的順序
- 包含列的索引:SQL Server索引進階 Level 5索引SQLServer
- java繼承關係下執行順序Java繼承
- 神奇的 SQL 之擦肩而過 → 真的用到索引了嗎SQL索引
- 你瞭解一條sql的執行順序嗎SQL
- 兩列複合索引中(交換索引中列的順序),選索引的原則是?因為索引名字ascii碼小?索引ASCII
- mysql 中sql語句關鍵字的書寫順序與執行順序MySql
- 軟體開發人員真的瞭解SQL索引嗎(聚集索引)SQL索引
- SQL Server資料庫調整表中列的順序操作方法及遇到問題SQLServer資料庫
- SQL Server 索引和表體系結構(包含列索引)SQLServer索引
- SQL Server中SELECT語句執行順序解析SQLServer
- Sql Server關於create index include帶有包含列的索引的最全解釋SQLServerIndex索引
- Sql執行順序SQL
- 標準的 SQL 解析順序SQL
- 主鍵local索引、unique local索引、分割槽索引順序的理解索引
- svg06——svg中座標變換與順序的關係SVG
- SQL優化--多表連線和走索引的關係SQL優化索引
- 關於SQL Server索引的最左匹配原則SQLServer索引
- 佇列-順序儲存佇列
- 順序佇列基本操作佇列
- SQL Server索引 - 非聚集索引SQLServer索引
- Java真的沒出路了嗎?Java
- PostgreSQL資料庫多列複合索引的欄位順序選擇原理SQL資料庫索引
- SQL 語句的執行順序SQL
- SQL 執行順序 你懂的SQL
- SQL Server 2008還原順序的高階注意事項SQLServer
- MapStruct與lombok載入順序問題與annotationProcessorPaths的關係?StructLombok
- load 和 initialize 方法的執行順序以及類和物件的關係物件
- MS SQL SERVER索引優化相關查詢SQLServer索引優化
- Sql Server關於indexed view索引檢視的總結SQLServerIndexView索引
- 關於SQL Server 2008的缺失索引功能SQLServer索引
- JavaScript 陣列順序打亂JavaScript陣列
- 佇列順序性引發的思考佇列
- 佇列的順序儲存結構佇列
- SQL Server 列儲存索引 第二篇:設計SQLServer索引
- SQL Server 列儲存索引 第三篇:維護SQLServer索引