主頁 > 資料庫 > SQL-索引

SQL-索引

2021-09-11 08:39:48 資料庫

理解“聚集索引”和“非聚集索引”

聚集索引(clustered   index,也稱聚類索引、簇集索引):把內容本身就是一種按照一定規則排列的目錄稱為“聚集索引”

       我們的漢語字典的正文本身就是一個聚集索引,比如,我們要查“安”字,就會很自然地翻開字典的前幾頁,因為“安”的拼音是“an”,而按照拼音排序漢字的字典是以英文字母“a”開頭并以“z”結尾的,那么“安”字就自然地排在字典的前部,如果您翻完了所有以“a”開頭的部分仍然找不到這個字,那么就說明您的字典中沒有這個字;同樣的,如果查“張”字,那您也會將您的字典翻到最后部分,因為“張”的拼音是“zhang”,也就是說,字典的正文部分本身就是一個目錄,您不需要再去查其他目錄來找到您需要找的內容,

② 非聚集索引(nonclustered   index,也稱非聚類索引、非簇集索引):目錄純粹是目錄,正文純粹是正文的排序方式稱為“非聚集索引”

       如果您認識某個字,您可以快速地從自動中查到這個字,但您也可能會遇到您不認識的字,不知道它的發音,這時候,您就不能按照剛才的方法找到您要查的字,而需要去根據“偏旁部首”查到您要找的字,然后根據這個字后的頁碼直接翻到某頁來找到您要找的字,但您結合“部首目錄”和“檢字表”而查到的字的排序并不是真正的正文的排序方法,比如您查“張”字,我們可以看到在查部首之后的檢字表中“張”的頁碼是672頁,檢字表中“張”的上面是“馳”字,但頁碼卻是63頁,“張”的下面是“弩”字,頁面是390頁,很顯然,這些字并不是真正的分別位于“張”字的上下方,現在您看到的連續的“馳、張、弩”三字實際上就是他們在非聚集索引中的排序,是字典正文中的字在非聚集索引中的映射,我們可以通過這種方式來找到您所需要的字,但它需要兩個程序,先找到目錄中的結果,然后再翻到您所需要的頁碼,

由以上解釋,就很容易理解:每個表只能有一個聚集索引,因為目錄只能按照一種方法進行排序,

 

索引使用的誤區

主鍵就是聚集索引

        通常,我們會在每個表中都建立一個 ID 列,以區分每條資料,并且這個 ID 列是自動增大的,步長一般為 1 ,這種 ID 是自動生成,我們并不知道每條記錄的ID號,所以我們很難在實踐中用 ID 號來進行查詢( 若要查詢需要提前知道要查詢記錄的 ID 號,這就有點本末倒置了 ),

② 只要建立索引就能顯著提高查詢速度

        并非是在任何欄位上簡單地建立索引就能提高查詢速度,因此建立“適當”的聚合索引對于我們提高查詢速度是非常重要的

③ 把所有需要提高查詢速度的欄位都加進聚集索引,以提高查詢速度

        僅用聚集索引的起始列作為查詢條件和同時用到復合聚集索引的全部列的查詢速度是幾乎一樣的,甚至比用上全部的復合索引列還要略快(在查詢結果集數目一樣的情況下);而如果僅用復合聚集索引的非起始列作為查詢條件的話,這個索引是不起任何作用的,

 

索引使用經驗總結

① 用聚合索引比用不是聚合索引的主鍵速度快

用聚合索引比用一般的主鍵作order   by時速度快,特別是在小資料量情況下

        如果資料量很小的話,用聚集索引作為排序列要比使用非聚集索引速度快得明顯的多;而資料量如果很大的話,如10萬以上,則二者的速度差別不明顯,

使用聚合索引內的時間段,搜索時間會按資料占整個資料表的百分比成比例減少,而無論聚合索引使用了多少個

④ 日期列不會因為有分秒的輸入而減慢查詢速度

 建立一個“適當”的索引體系,特別是對聚合索引的創建

        引有助于提高檢索性能,但過多或不當的索引也會導致系統低效,因為用戶在表中每加進一個索引,資料庫就要做更多的作業,過多的索引甚至會導致索引碎片,

 

不良的SQL

   不良的 SQL 往往來自于 不恰當的索引設計不充份的連接條件 和 不可優化的 where 子句 ,在對它們進行適當的優化后,其運行速度有了明顯地提高!

① 不恰當的索引設計

預設情況下建立的索引是非聚集索引,但有時它并不是最佳的;合理的索引設計要建立在對各種查詢的分析和預測上,一般來說:

有大量重復值、且經常有范圍查詢( between , > , < , >= , <= )和 order by 、group by 發生的列,可考慮建立聚集索引;

? 經常同時存取多列,且每列都含有重復值可考慮建立組合索引; 

? 組合索引要盡量使關鍵查詢形成索引覆寫,其前導列一定是使用最頻繁的列,

 不充份的連接條件

eg:表 card 有 7896行,在 card_no 上有一個非聚集索引,表 account 有 191122行,在 account_no 上有一個非聚集索引,試看在不同的表連接條件下,兩個 SQL 的執行情況:

1 select sum(a.amount) from account a,card b where a.card_no = b.card_no(20秒)
2 -- 將SQL改為:
3 select sum(a.amount) from account a,card b where a.card_no = b.card_no and a.account_no=b.account_no(< 1秒)
4 -- 在第一個連接條件下,最佳查詢方案是將 account 作外層表,card 作內層表,利用 card 上的索引,其 I/O 次數可由以下公式估算為: 5 ---- 外層表 account 上的 22541頁 +( 外層表 account 的 191122行 * 內層表 card 上對應外層表第一行所要查找的3頁 )= 595907 次 I/O

6 -- 在第二個連接條件下,最佳查詢方案是將 card 作外層表,account 作內層表,利用 account 上的索引,其 I/O 次數可由以下公式估算為: 7 ---- 外層表 card 上的 1944頁 +( 外層表 card 的 7896行 * 內層表 account 上對應外層表每一行所要查找的4頁 )= 33528 次 I/O

可見,只有充份的連接條件,真正的最佳方案才會被執行,

        多表操作在被實際執行前,查詢優化器會根據連接條件,列出幾組可能的連接方案并從中找出系統開銷最小的最佳方案,連接條件要充份考慮帶有索引的表、行數多的表,

       內外表的選擇可由公式:外層表中的匹配行數 * 內層表中每一次查找的次數確定,乘積最小為最佳方案,

 不可優化的 where 子句

        # where子句中對列的任何操作結果都是在SQL運行時逐列計算得到的,因此它不得不進行表搜索,而沒有使用該列上面的索引;如果這些結果在查詢編譯時就能得到,那么就可以被SQL優化器優化,使用索引,避免表搜索,

eg:

 1 select * from record where substring ( card_no , 1 , 4) ='5378'(13秒)
 2 --改為下面的SQL
 3 select * from record where card_no like '5378%'<1秒 )
 4 
 5 select * from record where amount/30 < 1000 ( 11秒 )
 6 --改為下面的SQL
 7 select * from record where amount < 1000*30<1秒)
 8 
 9 select * from record where convert ( char(10) , date , 112 ) = '19991201'(10秒)
10 --改為下面的SQL
11 select * from record where date= '1999/12/01'< 1秒)

# 所謂優化即where子句利用了索引,不可優化即發生了表掃描或額外開銷

eg:表 stuff 有 200000 行,id_no 上有非聚集索引,請看下面這個 SQL :

select count(*) from stuff where id_no in('0','1') (23秒)

       where條件中的 'in' 在邏輯上相當于 'or' ,所以語法分析器會將 in ( '0' , '1' ) 轉化為 id_no = '0' or id_no = '1' 來執行,

  我們期望它會根據每個 or 子句分別查找,再將結果相加,這樣可以利用 id_no 上的索引;但實際上( 根據 showplan ),它卻采用了 " OR 策略 " ,即先取出滿足每個 or 子句的行,存入臨時資料庫的作業表中,再建立唯一索引以去掉重復行,最后從這個臨時表中計算結果,因此,實際程序沒有利用 id_no 上索引,并且完成時間還要受 tempdb 資料庫性能的影響,

實踐證明,表的行數越多,作業表的性能就越差,當 stuff 有 620000行 時,執行時間竟達到 220秒 !還不如將 or 子句分開:

select count(*) from stuff where id_no='0'
select count(*) from stuff where id_no='1'

得到兩個結果,再作一次加法合算,因為每句都使用了索引,執行時間只有3秒,在 620000行 下,時間也只有 4秒,

用更好的方法,寫一個簡單的存盤程序:

 1 create proc count_stuff as
 2 declare @a int
 3 declare @b int
 4 declare @c int
 5 declare @d char(10)
 6 begin
 7 select @a=count(*) from stuff where id_no='0'
 8 select @b=count(*) from stuff where id_no='1'
 9 end
10 select @c=@a+@b
11 select @d=convert(char(10),@c)
12 print @d

直接算出結果,執行時間同上面一樣快!

由以上三點,可以總結以下結論

 

1.任何對列的操作都將導致表掃描,它包括資料庫函式、計算運算式等等,查詢時要盡可能將操作移至等號右邊,

 

2. in 、or 子句常會使用作業表,使索引失效;如果不產生大量重復值,可以考慮把子句拆開;拆開的子句中應該包含索引,

 

3.要善于使用存盤程序,它使 SQL 變得更加靈活和高效,

 

---- 從以上這些例子可以看出,SQL 優化的實質就是在結果正確的前提下,用優化器可以識別的陳述句,充份利用索引,減少表掃描的 I/O 次數,盡量避免表搜索的發生,

 

 

FILLFACTOR ( 填充因子 )

要理解填充因子的作用,首先需要理解什么是頁拆分

頁拆分

        在創建聚集索引時,表中的資料按照索引列中的值的順序存盤在資料庫的資料頁中,在表中插入新的資料行或更改索引列中的值時,SQL Server 必須重新組織表中的資料存盤,以便為新行騰出空間,保持資料的有序存盤,這同樣適用于非聚集索引,添加或更改資料時,SQL Server 不得不重新組織非聚集索引頁中的資料存盤,向一個已滿的索引頁添加某個新行時,SQL Server 把大約一半的行移到新頁中以便為新行騰出空間,這種重組稱為頁拆分,

        頁拆分會降低性能并使表中的資料存盤產生碎片,

填充因子的作用理解

       當創建一個新索引,或重建一個存在的索引時,你可以指定一個填充因子,它是在索引創建時索引里的資料頁被填充的數量,

       填充因子設定為 100 意味著每個索引頁 100% 填滿,50% 意味著每個索引頁 50% 填滿, 如果你創建一個填充因子為 100 的聚集索引( 在一個非單調遞增的列上 ),那意味著每當一個記錄被插入( 或修改 )時,頁拆分都會發生,因為在現存的頁上沒有這些資料的空間,

       eg:假定你剛剛用預設的填充因子新創建了一個索引,當sqlserver創建它時,它把索引放在相鄰的物理頁面上,因為資料能夠順序的讀所以這樣會有最優的i/o訪問,但當表隨著、、增加和改變時,發生了頁拆分,當頁拆分發生時,sqlserver必須在磁盤的某處分配一個新的頁,這些新的頁和最初的物理頁不是連續的,因此,訪問使用的是隨機的i/o,而不是有順序的i/o,這樣訪問索引頁會變得更慢,

填充因子如何設定比較好

原則:

低更改的表(讀寫比率為100:1):100%的填充因子

高更改的表(寫超過讀)50-70%的填充因子

讀寫各一半的:80-90%的填充因子 

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/299104.html

標籤:SQL Server

上一篇:MySQL45講之優化器選錯索引

下一篇:SQL-索引

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:33:24 more
  • MySQL中binlog備份腳本分享

    關于MySQL的二進制日志(binlog),我們都知道二進制日志(binlog)非常重要,尤其當你需要point to point災難恢復的時侯,所以我們要對其進行備份。關于二進制日志(binlog)的備份,可以基于flush logs方式先切換binlog,然后拷貝&壓縮到到遠程服務器或本地服務器 ......

    uj5u.com 2023-04-20 08:28:06 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:27:27 more
  • 快取與資料庫雙寫一致性幾種策略分析

    本文將對幾種快取與資料庫保證資料一致性的使用方式進行分析。為保證高并發性能,以下分析場景不考慮執行的原子性及加鎖等強一致性要求的場景,僅追求最終一致性。 ......

    uj5u.com 2023-04-20 08:26:48 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:26:35 more
  • 云時代,MySQL到ClickHouse資料同步產品對比推薦

    ClickHouse 在執行分析查詢時的速度優勢很好的彌補了MySQL的不足,但是對于很多開發者和DBA來說,如何將MySQL穩定、高效、簡單的同步到 ClickHouse 卻很困難。本文對比了 NineData、MaterializeMySQL(ClickHouse自帶)、Bifrost 三款產品... ......

    uj5u.com 2023-04-20 08:26:29 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:25:13 more
  • Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)

    Redis 報錯“OutOfDirectMemoryError(堆外記憶體溢位) ”問題如下: 一、報錯資訊: 使用 Redis 的業務介面 ,產生 OutOfDirectMemoryError(堆外記憶體溢位),如圖: 格式化后的報錯資訊: { "timestamp": "2023-04-17 22: ......

    uj5u.com 2023-04-20 08:24:54 more
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:24:03 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:23:11 more