like语句百分号前置会使用到索引吗?
原文轉載至:https://www.cnblogs.com/lyhabc/p/3378753.html
like語句百分號前置會使用到索引嗎?
前幾天看了這篇文章:談SQL Server對like '%關鍵詞%' 處理時的索引利用問題
看完了之后,我很想知道這篇文章是不是臨時工寫的?還是網站的主人寫的,網站的主人的微博我都有關注(在微博里私信過)
是某個公司的DBA,這里先不管他是不是臨時工寫的,今天我也研究一下這個問題o(∩_∩)o
?
說明:我們說的走索引指的是:聚集索引查找、非聚集索引查找
而全表掃描、聚集索引掃描、非聚集索引掃描都不是走索引
?
而這里說的走索引跟全文搜索/全文索引沒有關系??SQLSERVER全文搜索
全文搜索/全文索引已經是另外一種技術了
聚集索引表
SQL腳本如下:
表數據
聚集索引創建在GROUPNAME這個字段上,我們就查找GROUPNAME這個字段
如果看過我以前寫的文章的人肯定知道:查找只會出現在建立索引的時候的第一個字段(這里我就不再詳細敘述了)
1 --聚集索引查找 2 SELECT * FROM [dbo].[Department] WHERE [GroupName] LIKE '銷售組1000' 3 --聚集索引掃描 4 SELECT * FROM [dbo].[Department] WHERE [GroupName] LIKE '%銷售組1000%' 5 --聚集索引掃描 6 SELECT * FROM [dbo].[Department] WHERE [GroupName] LIKE '%銷售組1000' 7 --聚集索引查找 8 SELECT * FROM [dbo].[Department] WHERE [GroupName] LIKE '銷售組1000%'--------------------------------------------------------------------------
IO和時間統計
?View Code 1 (1 行受影響)LIKE '銷售組1000'2 表 'Department'。掃描計數 1,邏輯讀取 3 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。3 4 SQL Server 執行時間:5 CPU 時間 = 0 毫秒,占用時間 = 0 毫秒。6 7 SQL Server 執行時間:8 CPU 時間 = 0 毫秒,占用時間 = 0 毫秒。9 10 (11 行受影響)LIKE '%銷售組1000%' 11 表 'Department'。掃描計數 1,邏輯讀取 448 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。 12 13 SQL Server 執行時間: 14 CPU 時間 = 47 毫秒,占用時間 = 47 毫秒。 15 16 SQL Server 執行時間: 17 CPU 時間 = 0 毫秒,占用時間 = 0 毫秒。 18 19 (1 行受影響)LIKE '%銷售組1000' 20 表 'Department'。掃描計數 1,邏輯讀取 448 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。 21 22 SQL Server 執行時間: 23 CPU 時間 = 47 毫秒,占用時間 = 40 毫秒。 24 25 SQL Server 執行時間: 26 CPU 時間 = 0 毫秒,占用時間 = 0 毫秒。 27 28 (11 行受影響)LIKE '銷售組1000%' 29 表 'Department'。掃描計數 1,邏輯讀取 3 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。 30 31 SQL Server 執行時間: 32 CPU 時間 = 0 毫秒,占用時間 = 0 毫秒。 33 34 SQL Server 執行時間: 35 CPU 時間 = 0 毫秒,占用時間 = 0 毫秒。?
只有LIKE '銷售組1000'和LIKE '銷售組1000%'用到了查找
為什麼?我會在文中最后說明
非聚集索引表
SQL腳本如下:
我們drop掉剛才的department表
1 DROP TABLE [dbo].[Department]重新建立department表
?View Code非聚集索引依然建立在GROUPNAME這個字段上
?
表數據
同樣,我們使用上面講解聚集索引表時候的查詢語句
因為是select * 所以SQLSERVER需要到數據頁面去找其他的字段數據,使用到RID查找
這里的結果跟聚集索引是一樣的
-------------------------------------------------------------------------------------------
IO和時間統計
?View Code 1 (1 行受影響) LIKE '銷售組1000'2 表 'Department'。掃描計數 1,邏輯讀取 3 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。3 4 SQL Server 執行時間:5 CPU 時間 = 0 毫秒,占用時間 = 62 毫秒。6 7 SQL Server 執行時間:8 CPU 時間 = 0 毫秒,占用時間 = 0 毫秒。9 10 (11 行受影響)LIKE '%銷售組1000%' 11 表 'Department'。掃描計數 1,邏輯讀取 92 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。 12 13 SQL Server 執行時間: 14 CPU 時間 = 16 毫秒,占用時間 = 17 毫秒。 15 16 SQL Server 執行時間: 17 CPU 時間 = 0 毫秒,占用時間 = 0 毫秒。 18 19 (1 行受影響)LIKE '%銷售組1000' 20 表 'Department'。掃描計數 1,邏輯讀取 82 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。 21 22 SQL Server 執行時間: 23 CPU 時間 = 15 毫秒,占用時間 = 17 毫秒。 24 25 SQL Server 執行時間: 26 CPU 時間 = 0 毫秒,占用時間 = 0 毫秒。 27 28 (11 行受影響)LIKE '銷售組1000%' 29 表 'Department'。掃描計數 1,邏輯讀取 13 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。 30 31 SQL Server 執行時間: 32 CPU 時間 = 0 毫秒,占用時間 = 0 毫秒。 33 34 SQL Server 執行時間: 35 CPU 時間 = 0 毫秒,占用時間 = 0 毫秒。?
為什麼只有LIKE '銷售組1000'和LIKE '銷售組1000%'用到了查找???
如果閣下曾經有看過我寫的
SQLSERVER聚集索引與非聚集索引的再次研究(上)
SQLSERVER聚集索引與非聚集索引的再次研究(下)
您就會知道在聚集索引頁面和非聚集索引頁面里都有一個KeyHashValue的字段
聚集索引頁面
非聚集索引頁面
?
當使用?'%銷售組1000%'和'%銷售組1000'的時候,因為是模糊匹配(百分號前置)
SQLSERVER不會去匹配hash值(KeyHashValue),直接掃描(SCAN)算了
但是使用'銷售組1000'和'銷售組1000%'的時候
'銷售組1000' :SQLSERVER能夠準確匹配到唯一的一個hash值
'銷售組1000%':SQLSERVER會匹配與銷售組1000相同的hash值
與銷售組1000%匹配的記錄會有多個,所以邏輯讀取次數也會有多次
所以,'銷售組1000'和'銷售組1000%'能夠使用查找(SEEK)
總結
只有了解了SQLSERVER的內部原理,才能夠明白更多
?
注意:我這里并沒有將非聚集索引掃描納入到“走索引”這個分類,如果將非聚集索引掃描納入到“走索引”這個分類里
那么我的朋友的文章就是對的,隨便加個非聚集索引,讓表掃描/聚集索引掃描變成非聚集索引掃描,就認為是走索引
(雖然非聚集索引掃描比聚集索引掃描/表掃描快,IO少)
那么下面四個語句都是屬于走索引,沒有什么好討論的,我們討論的前提是在基礎表上不加任何東西,如果在做實驗的過程中
隨便加個非聚集索引,然后走非聚集索引掃描就說走索引,那么這篇文章就沒有意義了,經過再三斟酌,
我決定將“非聚集索引掃描”移出“走索引”這個分類,畢竟查找(SEEK)比掃描(SCAN)快
SELECT * FROM [dbo].[Department] WHERE [GroupName] LIKE '銷售組1000'
SELECT * FROM [dbo].[Department] WHERE [GroupName] LIKE '%銷售組1000%'
SELECT * FROM [dbo].[Department] WHERE [GroupName] LIKE '%銷售組1000'
SELECT * FROM [dbo].[Department] WHERE [GroupName] LIKE '銷售組1000%'
?
最最后,補充說一下
我們判斷一個執行計劃的性能的好壞的標準是什么??
就是哪個執行計劃的邏輯讀次數最少
Logical reads:包含該語句從內存數據緩沖區中訪問的頁數和從物理磁盤讀取的頁數。
如果全表掃描/聚集索引掃描所使用的邏輯讀比聚集索引查找/非聚集索引查找使用的邏輯讀要少,
或者全表掃描比非聚集索引掃描使用的邏輯讀要少
那么SQLSERVER選擇全表掃描/聚集索引掃描這個執行計劃就是好的
有些人為了讓SQLSERVER使用索引,不惜代價使用查詢提示,讓SQLSRVER去走索引,這樣是得不償失的
我們的最終目的是:減少邏輯讀次數,不要為了索引而索引!!
當然,我這里的實驗環境跟各位的真實環境會有差別,不過“邏輯讀次數”這個標準無論是哪個環境都是一樣的!!
我說完了,謝謝大家o(∩_∩)o
?
physical reads:表示那些沒有駐留在內存緩沖區中需要從磁盤讀取的數據頁。
Read-ahead reads是SQL Server為了提高性能而產生的預讀。
如有不對的地方,歡迎大家拍磚o(∩_∩)o
轉載于:https://www.cnblogs.com/mkl34367803/p/9124600.html
總結
以上是生活随笔為你收集整理的like语句百分号前置会使用到索引吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python文件分享(3为http.se
- 下一篇: JS 函数参数arguments对象(实