數據庫索引是優化任何數據庫系統性能的關鍵組成部分。如果沒有有效的索引,您的數據庫查詢可能會變得緩慢且低效,從而導致用戶體驗不佳並降低生產力。在這篇文章中,我們將探討創建和使用數據庫索引的一些最佳實踐。
作者:The Java Trail
本文和封面來源:https://medium.com/,愛可生開源社區翻譯。
本文約 2700 字,預計閱讀需要 9 分鐘。
數據庫中使用多種索引算法來提高查詢性能。以下是一些最常用的索引算法:
B 樹(B-Tree)索引
B-Tree 索引是一種自平衡樹數據結構,可保持數據排序並允許在對數時間內搜索、順序訪問、插入和刪除。 B-Tree 索引結構廣泛應用於數據庫和文件系統中。 B-Tree 索引廣泛應用於 MySQL、PostgreSQL 等關係數據庫中。
B-Tree 索引針對範圍查詢進行了優化,因爲它們可以有效地查找某個值範圍內的所有記錄。這是因爲記錄在索引中按排序順序存儲。利用在使用 =
、>
、>=
、<
、<=
或 BETWEEN
運算符的表達式中使用列比較。
例如,假設我們有一個具有以下表結構的產品表:
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(255),
price DECIMAL(10,2)
);
我們可以通過以下 SQL 語句爲 price
字段添加一個 B-Tree 索引。
CREATE INDEX products_price_index ON products (price);
哈希(Hash)索引
哈希索引是另一種流行的索引算法,用於加速查詢。哈希索引使用哈希函數將鍵映射到索引位置。此索引算法對於精確匹配查詢最有用,例如根據主鍵值搜索特定記錄。哈希索引通常用於內存數據庫,例如 Redis。
哈希索引的工作原理是根據哈希值將表中的每條記錄映射到唯一的存儲桶。哈希值是使用哈希函數計算的,哈希函數是一種以數據項作爲輸入並返回唯一整數值的數學函數。
爲了在哈希索引中查找記錄,數據庫計算搜索鍵的哈希值,然後查找相應的存儲桶。如果該記錄在存儲桶中,則數據庫將返回該記錄。否則,數據庫執行全表掃描。
哈希索引的查找速度非常快,但它們不能用於有效地查詢數據範圍。這是因爲哈希函數不保留表中記錄之間的任何順序。
要使用哈希索引執行查詢:
- 數據庫計算查詢條件的哈希值。
- 在哈希表中查找對應的哈希桶。
- 然後數據庫檢索指向表中具有相應哈希值的行的指針。
- 使用這些指針從表中檢索實際行。
假設我們有一個具有以下表結構的產品表:
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(255),
price DECIMAL(10,2)
);
問:哈希索引沒有像 B-Tree 那樣進行優化的情況?
在某些情況下,哈希索引可能不是最佳選擇:
- 哈希索引在查找方面比樹索引更快(對於使用
=
或<=>
運算符的相等比較),但它們不能用於有效地查詢數據範圍。 - 查找時樹索引比哈希索引慢,但它們可以用來有效查詢數據範圍。
範圍查詢: 哈希索引未針對範圍查詢進行優化,在範圍查詢中您需要查找某個值範圍內的記錄(使用 =
、>
、>=
、<
、<=
或 BETWEEN
運算符)。在這種情況下,B-Tree 索引會更合適。
排序: 哈希索引未針對排序進行優化,您需要根據特定列對記錄進行排序。在這種情況下,B-Tree 索引或聚集索引會更合適。
大型數據集: 哈希索引可能會佔用大量內存,因此它們可能不適合需要考慮內存使用情況的大型數據集。
我們可以使用以下命令在 name
列上創建哈希索引:
CREATE INDEX products_name_hash ON products (name);
SELECT * FROM products WHERE name = 'iPhone 13 Pro';
CREATE INDEX products_name_tree ON products (name);
SELECT * FROM products WHERE name = 'iPhone 13 Pro';
如果我們使用哈希索引,數據庫會計算搜索鍵“iPhone 13 Pro”的哈希值,然後查找對應的桶。由於哈希函數是確定性的,因此數據庫總是會在同一個桶中找到記錄,無論記錄在表中的存儲順序如何。
如果我們使用樹索引,數據庫將從樹的根部開始,並將搜索鍵“iPhone 13 Pro”與存儲在根部的鍵的值進行比較。由於樹是排序的,數據庫將很快找到包含搜索鍵的記錄。
問:爲什麼 B-Tree 對於 Range 查詢比 Hash 索引更優化?
現在,假設我們要查找價格在 100 美元到 200 美元之間的所有產品。我們可以使用以下查詢:
SELECT * FROM products WHERE price BETWEEN 100 AND 200;
工作原理
B-Tree
B-Tree 索引通過按排序順序存儲記錄來工作。要在 B-Tree 索引中查找記錄,
- 數據庫從樹的根部開始,並將搜索關鍵字與存儲在根部的關鍵字的值進行比較。
- 如果搜索鍵等於根鍵,則數據庫返回該記錄。
- 否則,數據庫根據比較結果確定下一步要搜索哪一個子樹。
Hash
Hash 索引的工作原理是根據哈希值將表中的每條記錄映射到唯一的存儲桶。哈希值是使用哈希函數計算的。哈希索引將數據隨機分佈在存儲桶中,導致範圍查詢效率低下。檢索一系列值(例如 100 美元到 200 美元之間的價格)需要掃描該範圍內的所有存儲桶,這實際上會導致全表掃描。哈希索引擅長快速精確匹配查找,但缺乏高效範圍查詢所需的數據排序。
問,爲什麼 B-Tree 索引在排序方面比 Hash 索引更優化?
B-Tree 樹索引比哈希索引對數據進行排序更有效,因爲它們按排序順序存儲記錄。這允許數據庫按排序順序快速迭代記錄。
Hash 索引的工作原理是根據哈希值將表中的每條記錄映射到唯一的存儲桶。這意味着桶中記錄的順序是隨機的。要對記錄進行排序,數據庫需要迭代所有存儲桶,然後對每個存儲桶中的記錄進行排序。這比使用 B-Tree 索引慢,後者按排序順序存儲記錄。
我們可以使用以下命令在 price
列上創建 B-Tree 索引:
CREATE INDEX products_price_index ON products (price);
現在,假設我們要按價格升序對產品進行排序。我們可以使用以下查詢:
SELECT * FROM products ORDER BY price ASC;
數據庫將使用 B 樹索引按排序順序快速迭代產品。
哈希索引缺點:
- 哈希索引不支持範圍查詢或排序
- 哈希索引會消耗大量內存
- 哈希索引不適合頻繁更新的數據庫
位圖(Bitmap)索引
位圖索引用於具有少量不同值的列,例如布爾列或性別列。位圖索引對於基數較低的列來說非常緊湊且高效。
SELECT * FROM employees WHERE gender = 'Female';
位圖索引對於基數較低的列非常高效,允許快速設置操作,例如並集和交集。非常適合臨時報告和數據倉庫。
全文(Full-Text)索引
全文索引用於索引大量文本數據,例如文檔或網頁。該索引算法將文本分解爲單詞或標記,並以允許高效搜索操作的方式對它們進行索引。全文索引對於涉及在文本中搜索特定單詞或短語的查詢最有用。全文索引通常用於 Elasticsearch 等搜索引擎。
電子商務全文索引的用例:
通過全文索引,電子商務應用程序可以根據用戶輸入的搜索查詢快速搜索大型產品目錄。全文索引允許基於多個單詞和短語進行搜索,包括拼寫錯誤、同義詞,甚至相關概念。這使得用戶更容易找到他們正在尋找的東西,即使他們不知道確切的產品名稱或描述。
例如,假設一位顧客正在尋找一雙新的跑鞋。他們在搜索欄中輸入“跑鞋”。通過全文索引,電子商務應用程序可以快速搜索所有產品描述、名稱和標籤,以查找與跑鞋相關的所有產品。搜索結果將根據相關性進行排序,相關性由搜索詞在產品信息中出現的頻率決定。
如果沒有全文索引,搜索可能只會查看產品名稱,而無法考慮可能與客戶相關的其他因素,例如產品描述或標籤。此外,搜索可能無法處理拼寫錯誤或相關概念,例如“慢跑鞋”或“運動鞋”。
假設我們有一個名爲 products
的表,其中包含以下列:id
、name
、description
和 tags
。
CREATE FULLTEXT INDEX products_ft_index ON products(name, description, tags);
現在,假設一位顧客搜索“跑鞋”。我們可以使用以下查詢來搜索與搜索詞相關的產品:
SELECT id, name, description, MATCH(name, description, tags) AGAINST('running shoes') as relevance
FROM products
WHERE MATCH(name, description, tags) AGAINST('running shoes' IN BOOLEAN MODE)
ORDER BY relevance DESC
相關性分數基於每個產品與搜索詞的匹配程度,分數越高表示匹配越接近。結果根據相關性得分按降序排序,因此相關性得分最高的產品(耐克跑鞋)顯示在列表頂部。
下面是另一個示例查詢,用於搜索包含“organic”和“coffee”一詞的產品:
SELECT id, name, description, MATCH(name, description, tags) AGAINST('+"organic" +"coffee"') as relevance
FROM products
WHERE MATCH(name, description, tags) AGAINST('+"organic" +"coffee"' IN BOOLEAN MODE)
ORDER BY relevance DESC;
該查詢正在搜索名稱、描述或標籤列中同時具有“organic”和“coffee”關鍵字的所有產品。每個結果的相關性得分也是根據關鍵字在列中出現的次數和位置來計算的。
輸出將包含“id”、“name”、“description”和“relevance”列,結果按“relevance”列降序排列。
優點
- 全文索引對於基於文本的列非常有效
- 非常適合搜索引擎和內容管理系統
- 支持搜索結果的相關性排序
缺點
- 全文索引會佔用大量存儲空間
- 對於非常大的數據集,性能可能會下降
- 全文索引不適合數字或分類數據
更多技術文章,請訪問:https://opensource.actionsky.com/
關於 SQLE
SQLE 是一款全方位的 SQL 質量管理平臺,覆蓋開發至生產環境的 SQL 審覈和管理。支持主流的開源、商業、國產數據庫,爲開發和運維提供流程自動化能力,提升上線效率,提高數據質量。