摘要:索引就是資料表中資料和相應的儲存位置的列表,利用索引可以提高在表或檢視中的查詢資料的速度。
本文分享自華為雲社群《資料庫開發指南(六)索引和檢視的使用技巧、方法與綜合應用》,作者: bluetata 。
索引就是資料表中資料和相應的儲存位置的列表,利用索引可以提高在表或檢視中的查詢資料的速度。它類似於書籍的索引,可以幫助快速定位和檢索資料。在資料庫中,索引是對一個或多個列的值進行排序和儲存的結構,它們包含指向實際資料位置的指標。
資料庫中索引主要分為兩類:聚集索引和非聚集索引。SQL Server 還提供了唯一索引、索引檢視、全文索引、XML 索引等等。聚集索引和非聚集索引是資料庫引擎中索引的基本型別,是理解其他型別索引的基礎。
聚集索引是值表中資料行的物理儲存順序和索引的儲存順序完全相同。聚集索引根據索引順序物理地重新排列了使用者插入到表中的資料,因此,每個表只能建立一個聚集索引。聚集索引經常建立在表中經常被搜尋到的列或按順序存取的列上。在預設情況下,主鍵約束自動建立聚集索引。
非聚集索引不改變表中資料列的物理儲存位置,資料與索引分開儲存,通過索引指向的地址與表中的資料發生關係。
非聚集索引沒有改變表中物理行的位置,索引可以在以下情況下使用非聚集索引:
這裡用一個表格簡單的總結一下聚集索引和非聚集索引的區別:
除了以上索引,還有以下型別索引:
create [unique] [clustered | noclustered]
index index_name
on table_name (column_name ...)
[with fillfactor=x]
引數解釋
unique 唯一索引
clustered 聚集索引
noclustered 非聚集索引
fillfactor 填充因子大小,範圍在 0-100 直接,表示索引頁填滿的空間所佔的百分比。
在 MSSQL 中,索引的命名規則的最佳實踐可以有一些常見的準則,以提高可讀性和維護性。這個潛在的要求不僅試用於 SQL Server 資料庫,同樣在其他資料庫例如 MySQL、Oracle 中都同樣值得注意。
下面是個人總結的一些命名規則與建議:
-- 普通索引 if (exists (select * from sys.indexes where name = 'idx_stu_name')) drop index student.idx_stu_name go create index idx_stu_name on student(name); -- 聯合索引 if (exists (select * from sys.indexes where name = 'idx_uqe_clu_stu_name_age')) drop index student.idx_uqe_clu_stu_name_age go create unique clustered index idx_uqe_clu_stu_name_age on student(name, age); if (exists (select * from sys.indexes where name = 'idx_cid')) drop index student.idx_cid go if (exists (select * from sys.indexes where name = 'idx_cid')) drop index student.idx_cid go -- 非聚集索引 create nonclustered index idx_cid on student (cid) with fillFactor = 30; --填充因子 -- 聚集索引 if (exists (select * from sys.indexes where name = 'idx_sex')) drop index student.idx_sex go create clustered index idx_sex on student(sex); -- 聚集索引 if (exists (select * from sys.indexes where name = 'idx_name')) drop index student.idx_name go create unique index idx_name on student(name);
一般情況,可以選擇那些對查詢效能有積極影響的列進行索引建立,下面進行一定的總結:
列的選擇性:選擇性是指列中不同值的數量與總行數的比例。如果某列具有較高的選擇性,即不同的值較多,那麼為該列建立索引可能會有更好的效果。例如,在表示性別的列上建立索引可能沒有太大的幫助,因為只有兩個可能的值。
查詢頻率:觀察經常用於查詢條件的列。如果某個列經常用於搜尋、過濾或連線操作,那麼為該列建立索引可以提高查詢效能。
資料表的大小:對於大型表,建立索引的影響可能更加顯著。較小的表可能不需要太多的索引,因為全表掃描的開銷相對較小。
資料更新頻率:索引的建立和維護也會增加對資料的寫操作的開銷。如果某個列的資料經常發生變化,那麼建立索引可能會帶來一定的效能開銷。
查詢效能優化需求:通過分析查詢執行計劃,可以確定是否存在潛在的效能瓶頸,並考慮為相關的列建立索引以改善查詢效能。
請注意過多的索引也可能會帶來維護開銷和儲存成本,因此需要在權衡索引數量和效能提升之間找到平衡點。定期監控和評估索引的使用情況也是重要的,以確保索引仍然對資料庫效能產生積極影響。
雖然在某些情況下建立索引可以提高查詢效能,但並不是所有列都適合建立索引。以下是一些不適合建立索引的列的情況:
低選擇性列:如果某個列的選擇性很低,即該列的不同值較少,建立索引可能不會帶來明顯的效能提升。例如,對於性別這樣只有幾個可能值的列,建立索引可能不會有太大意義。
經常更新的列:如果某個列的值經常被修改,那麼為該列建立索引可能會帶來額外的維護成本和效能開銷。每次更新操作都需要更新索引,這可能會影響寫入效能。在這種情況下,需要仔細評估是否真的需要為該列建立索引。
過於頻繁的查詢列:某些列可能經常被查詢,但它們的選擇性較低,即不同的值較少。在這種情況下,儘管查詢頻率高,但為該列建立索引可能不會帶來明顯的效能提升,因為索引的使用效果有限。
大文字或大二進位制列:對於儲存大文字或大二進位制資料的列,如長文字欄位或影象欄位,建立索引的效果通常較差。這是因為索引本身需要佔用額外的儲存空間,並且對於大型資料的索引操作可能變得非常耗時。
不常用的列:對於很少用於查詢的列,建立索引可能沒有太大意義。如果一個列很少用於查詢條件或連線操作,那麼為其建立索引可能只會增加額外的開銷而不帶來實際的效能提升。
需要注意的是,以上列舉的情況只是一般性的指導原則,具體是否適合建立索引還取決於具體的資料庫結構、查詢模式和效能需求。在設計和建立索引時,應根據具體情況進行評估,並進行效能測試和優化以確保索引的有效性。
檢視就是一個虛擬的資料表,該資料表中的資料記錄是由一條查詢語句的查詢結果得到的。
如果你在面試的時候被問到這個問題,建議從下面這個流程來回答一下面試官。
首先介紹一下表的作用(比如表是直接儲存結構化資料,可以擴充套件增刪改之類的),之後在介紹一下檢視是什麼,之後從兩個切入點來講解檢視的好處以及必要性,這兩個切入點是:複用性和安全性,這裡來簡單總結一下:
講解完上述的兩個大的關鍵點後,也可以適當自行發揮,比如檢視你可以調整表欄位的顯示順序,或者欄位名字等等。這些也是優點。可以適當進行講解。
建立檢視的時候,對命名檢視大家一般也有預設的規則,一般情況可以使用 v_ 或 view_ + 表名(表縮寫)的形式。
例如:v_student
--建立檢視 if (exists (select * from sys.objects where name = 'v_student')) drop view v_student go create view v_student as select id, name, age, sex from student;
建立檢視需要考慮一下準則:
下列情況必須指定檢視中每列的名稱:
修改檢視和修改表有點類似,可以直接使用 alter 關鍵字進行修改,範例如下:
alter view v_student as select id, name, sex from student; alter view v_student(編號, 名稱, 性別) as select id, name, sex from student go select * from v_student; select * from information_schema.views;
如果你對某一個檢視有保護查詢邏輯、防止修改或者查詢加密的需求的時候,可以使用加密檢視操作。
在 SQL Server 中 使用with encryption後,可以在建立檢視時對其定義的 SQL 查詢進行加密。也就是說 MSSQL 會對該檢視的定義中的查詢語句進行加密。這意味著其他人無法直接檢視或分析該檢視的查詢邏輯。壓根就看不到這個檢視內部結構了。
-- 加密檢視 if (exists (select * from sys.objects where name = 'v_student_info')) drop view v_student_info go create view v_student_info with encryption --加密 as select id, name, age from student go --view_definition is null select * from information_schema.views where table_name like 'v_student';
如何解密被加密的檢視,或者修改已經被加密的檢視:
一般情況一個檢視被加密後,你需要修改它,那麼大致有3個方法:
檢視可以被更新嗎?什麼情況下可以被更新?
如果面試官問了這兩個問題,那麼他還算友好的提醒了你,如果直接問了一句話「檢視可以被更新嗎?」,那麼我感覺有被挖坑的嫌疑。
檢視可以被更新,但不是所有的情況都可以。
檢視更新必須遵循以下規則: