mysql索引使用基礎

1.創建&刪除

MySQL可以通過CREATE、ALTER、DDL三種方式創建一個索引。

在MySQL中,使用CREATE INDEX語句可以創建索引。具體語法如下:

CREATE INDEX indexName ON tableName (columnName(length) [ASC|DESC]);
 
其中,indexName是索引的名稱,tableName是要在其上創建索引的表名,columnName是要創建索引的列名,length是可選參數,用於指定索引的長度,ASC表示升序排序,DESC表示降序排序。

例如,如果要在名爲students的表上爲name列創建一個名爲index_name的索引,可以使用以下語句:

CREATE INDEX index_name ON students (name);
 
如果要在名爲employees的表上爲age列創建一個名爲index_age的索引,並按照年齡降序排序,可以使用以下語句:

CREATE INDEX index_age ON employees (age DESC);

 

在MySQL中,使用ALTER TABLE語句可以添加索引。具體語法如下:
ALTER TABLE tableName ADD INDEX indexName(columnName(length) [ASC|DESC]);

其中,tableName是要在其上添加索引的表名,indexName是索引的名稱,columnName是要創建索引的列名,length是可選參數,用於指定索引的長度,ASC表示升序排序,DESC表示降序排序。

例如,如果要在名爲students的表上爲name列創建一個名爲index_name的索引,可以使用以下語句:
ALTER TABLE students ADD INDEX index_name(name);

    
如果要在名爲employees的表上爲age列創建一個名爲index_age的索引,並按照年齡降序排序,可以使用以下語句:
ALTER TABLE employees ADD INDEX index_age(age DESC);

 

在MySQL中,使用CREATE TABLE語句可以創建表。具體語法如下:
CREATE TABLE tableName(
  columnName1 dataType NOT NULL,
  columnName2 dataType,
  ....,
  INDEX indexName (columnName(length))
);

    
其中,tableName是要創建的表名,columnName是列名,dataType是數據類型,NOT NULL表示該列不能爲空,indexName是索引的名稱,columnName(length)是要創建索引的列名和長度。

例如,如果要創建一個名爲students的表,包含id、name和age三個列,併爲name列創建一個名爲index_name的索引,可以使用以下語句:
CREATE TABLE students(
  id INT(8) NOT NULL,
  name VARCHAR(50),
  age INT(3),
  INDEX index_name (name)
);

 

mysql中沒有修改索引語句,只能刪除然後再重新添加

在MySQL中,使用DROP INDEX語句可以刪除索引。具體語法如下:
DROP INDEX indexName ON tableName;
  
其中,indexName是要刪除的索引名稱,tableName是要在其上刪除索引的表名。
例如,如果要從名爲students的表中刪除名爲index_name的索引,可以使用以下語句:
DROP INDEX index_name ON students;

  

2.索引本質

數據庫索引的本質是一種數據結構,用於提高數據庫查詢的性能。

索引的工作原理基於爲數據庫表中的一列或多列創建一個額外的數據結構,這個數據結構允許快速地定位到存儲數據的位置,從而加快查詢速度。具體來說,索引通常包含兩列:索引字段和指向原記錄

指針。索引表按照索引字段的值進行排序,這樣在執行查詢時,數據庫管理系統(DBMS)可以採用高效的查找算法(如二分查找)來快速定位到所需的記錄。

以下是索引的具體優點和缺點:

優勢:

  1. 提高檢索速度:索引可以顯著加快數據的查詢速度,尤其是當表中數據量較大時更爲明顯。通過索引,數據庫能夠快速定位到所需數據,避免全表掃描。
  2. 保證數據唯一性:唯一索引確保了數據庫表中每一行數據的唯一性,這對於維護數據的完整性非常重要。
  3. 加速連接操作:在涉及多表連接的查詢中,有索引的列可以加速表與表之間的連接操作。
  4. 減少排序和分組時間:在使用ORDER BY或GROUP BY子句進行數據檢索時,索引可以減少查詢中的排序和分組時間。
  5. 優化性能:正確創建和使用索引是實現高性能查詢的基礎,有助於提高整個系統的性能。

劣勢:

  1. 佔用空間:每個索引都會佔用一定的物理空間,如果建立聚簇索引,所需的空間會更大。
  2. 維護成本:創建和維護索引需要耗費時間,這種時間隨着數據量的增加而增加。
  3. 降低數據維護速度:在進行INSERT、UPDATE、DELETE等操作時,由於索引需要動態維護,這些操作的速度會相應降低。
  4. 查詢優化器選擇:有時候,即使存在索引,查詢優化器也可能會選擇不使用索引,特別是在評估索引帶來的性能提升不足以彌補其維護成本時。

總的來說,索引雖然在空間和更新操作上有所犧牲,但換來的是查詢效率的大幅提升。在設計數據庫時,合理使用索引是優化性能的重要手段之一。

3.索引區分

從表字段的層次來看,索引又可以分爲單列索引和多列索引,這兩個稱呼也比較好理解,單列索引是指索引是基於一個字段建立的,多列索引則是指由多個字段組合建立的索引。

3.1.單列索引

在數據庫中,單列索引可以根據其約束條件和用途分爲幾種類型,每種類型都有其特定的特點。以下是常見的單列索引類型及其特點:

  1. 普通索引(Regular Index):

    • 特點:允許列中有重複值和空值。
    • 目的:加速對指定列的查詢。
  2. 唯一索引(Unique Index):

    • 特點:不允許列中有重複值,但可以有空值。
    • 目的:加速查詢,並保證列中值的唯一性。
  3. 主鍵索引(Primary Key Index):

    • 特點:不允許列中有重複值或空值。
    • 目的:加速查詢,並強制表的每一行都唯一。
  4. 全文索引(Fulltext Index):

    • 特點:用於全文搜索,支持基於文本內容的查詢,通常用於VARCHARTEXT類型的列。
    • 目的:加速全文搜索。

創建索引的SQL語句示例(以MySQL爲例):

-- 創建普通索引
CREATE INDEX index_name ON table_name(column_name);

-- 創建唯一索引
CREATE UNIQUE INDEX unique_index_name ON table_name(column_name);

-- 創建主鍵索引
ALTER TABLE table_name
ADD PRIMARY KEY (column_name);

-- 創建全文索引(僅適用於支持全文索引的存儲引擎,如InnoDB)
ALTER TABLE table_name
ADD FULLTEXT INDEX fulltext_index_name(column_name);

 

創建索引的SQL代碼示例:

-- 假設我們有一個名爲 `users` 的表,包含 `id`, `username`, `email` 列

-- 創建普通索引
CREATE INDEX idx_users_username ON users(username);

-- 創建唯一索引,以確保每個用戶有唯一的電子郵件地址
CREATE UNIQUE INDEX idx_users_email ON users(email);

-- 設置 `id` 爲主鍵,自動創建主鍵索引
ALTER TABLE users
ADD PRIMARY KEY (id);

-- 如果表支持全文搜索,可以創建一個全文索引來優化對 `content` 列的搜索
CREATE FULLTEXT INDEX ft_users_content ON users(content);

 

3.2.多列索引

多列索引是一種在多個列上創建的索引,它允許根據多個列的值進行查詢。多列索引可以提供更高效的查詢性能,特別是在需要對多個列進行篩選或排序的情況下。

以下是常見的多列索引類型及其特點:

  1. 聯合索引(Composite Index):

    • 特點:基於多個列的值創建一個索引。
    • 目的:加速涉及多個列的查詢操作。
  2. 覆蓋索引(Covering Index):

    • 特點:包含查詢所需的所有數據的索引。
    • 目的:避免額外的數據訪問,提高查詢性能。
  3. 前綴索引(Prefix Index):

    • 特點:只包含指定列的前N個字符的索引。
    • 目的:減少索引的大小,提高查詢性能。
  4. 全文索引(Fulltext Index):

    • 特點:用於全文搜索,支持基於文本內容的查詢,通常用於VARCHARTEXT類型的列。
    • 目的:加速全文搜索。

創建多列索引的SQL語句示例(以MySQL爲例):

-- 創建聯合索引
CREATE INDEX index_name ON table_name(column1, column2);

-- 創建覆蓋索引
CREATE INDEX index_name ON table_name(column1, column2, ..., columnN);

-- 創建前綴索引
CREATE INDEX index_name ON table_name(column_name(N));

-- 創建全文索引(僅適用於支持全文索引的存儲引擎,如InnoDB)
ALTER TABLE table_name
ADD FULLTEXT INDEX fulltext_index_name(column_name);

 

創建多列索引的SQL代碼示例:

-- 假設我們有一個名爲 `orders` 的表,包含 `customer_id`, `order_date`, `total_amount` 列

-- 創建聯合索引,以便根據客戶ID和訂單日期進行查詢
CREATE INDEX idx_orders_customer_date ON orders(customer_id, order_date);

-- 創建覆蓋索引,以便根據客戶ID、訂單日期和總金額進行查詢,而無需額外訪問表數據
CREATE INDEX idx_orders_covering ON orders(customer_id, order_date, total_amount);

-- 創建前綴索引,以便根據客戶ID的前5個字符進行查詢
CREATE INDEX idx_orders_customer_prefix ON orders(customer_id(5));

-- 如果表支持全文搜索,可以創建一個全文索引來優化對 `description` 列的搜索
CREATE FULLTEXT INDEX ft_orders_description ON orders(description);

請注意,創建索引時需要考慮表中數據的特點和查詢模式。不當的索引可能會導致性能問題,例如,頻繁更新的列不適合創建索引,因爲它會導致索引維護的成本增加。此外,索引雖然可以提高查詢速度,但也會佔用額外的存儲空間,並在插入、更新和刪除操作時增加開銷。因此,在創建索引前應進行仔細的規劃和考慮。

 

4.索引注意點

4.1.建立索引時需要遵守以下原則

  1. 選擇唯一性索引:唯一性索引可以更快速地通過該索引來確定某條記錄,因爲唯一性索引的值是唯一的。
  2. 爲經常需要排序、分組和聯合操作的字段建立索引:如果某個字段經常用來做查詢條件,那麼該字段的查詢速度會影響整個表的查詢速度。因此,爲這樣的字段建立索引,可以提高整個表的查詢速度。
  3. 最左前綴匹配原則:在使用SQL語句時,如果WHERE部分的條件不符合最左匹配原則,可能導致索引失效,或者不能完全發揮建立的索引的功效。
  4. =和in可以亂序:比如a = 1 and b = 2 and c = 3建立 (a,b,c)索引可以任意順序,MySQL的查詢優化器會幫你優化成索引可以識別的形式。
  5. 儘量選擇區分度高的列作爲索引:區分度的公式是:count (distinct col)/count (*)。區分度越高,索引的效果越好。
  6. 不要建立過多的索引:因爲索引本身會佔用存儲空間。
  7. 考慮字段值長度較短的字段建立索引:如果字段值太長,會降低索引的效率。

4.2.聯合索引的最左前綴原則

聯合索引的最左前綴原則是指在使用聯合索引進行查詢時,查詢條件需要遵循索引中列的順序,從左到右進行匹配。

最左前綴原則是數據庫優化中的一個重要概念,它要求在使用聯合索引時,查詢條件必須包含索引列的最左端開始的一個或多個連續的列。這個原則確保了數據庫能夠有效地使用索引來加速查詢。以下是

一些關鍵點:

  • 查詢條件的順序:查詢條件中的列必須按照聯合索引中列的順序出現。例如,如果有一個聯合索引(a, b, c),那麼查詢條件中必須首先包含列a,然後是列b,最後是列c。
  • 部分使用索引:如果查詢條件只涉及到聯合索引中的部分列,那麼只有這些列的索引會被利用。例如,如果查詢條件只包含列a和列b,那麼只有這兩部分的索引會被用於查詢。
  • 範圍查詢的影響:當遇到範圍查詢(如大於、小於、BETWEEN等)時,最左前綴原則會停止匹配。這意味着,如果範圍查詢出現在聯合索引的某個列上,那麼該列右側的所有列都無法使用索引。
  • 調整索引順序:根據業務需求和查詢模式,可以調整聯合索引中列的順序,以優化查詢性能。例如,如果查詢經常涉及列a、列b和列d,但很少涉及列c,則可以考慮創建(a, b, d, c)的聯合索引。

以下是一個具體的示例來說明最左前綴原則的應用:

假設有一個表users,其包含id, username, email等字段,並且在這個表上創建了一個聯合索引idx_username_email(包含usernameemail兩個字段)。

CREATE INDEX idx_username_email ON users(username, email);

根據最左前綴原則,以下幾種查詢方式是符合最左前綴原則的:

 

  1.使用usernameemail進行查詢,能夠完全利用索引:

SELECT * FROM users WHERE username = '張三' AND email = '[email protected]';

 

  2.只使用username進行查詢,能夠部分利用索引:

SELECT * FROM users WHERE username = '張三';

  3.使用username進行範圍查詢,只能利用到第一列的索引:

SELECT * FROM users WHERE username LIKE '張%';

 

而以下查詢方式則不符合最左前綴原則,可能導致索引失效:

  1.只使用email進行查詢,沒有利用到最左側的username

SELECT * FROM users WHERE email = '[email protected]';

  2.使用username進行範圍查詢後,又使用了email進行等於查詢,但因爲範圍查詢的存在,email的索引將不會生效:

SELECT * FROM users WHERE username > '張三' AND email = '[email protected]';

 

4.3.索引失效

在MySQL中,即使爲表的字段創建了索引,也可能由於查詢語句的寫法或數據的特性導致索引失效。以下是一些可能導致索引失效的情況,以及相應的SQL示例:

  1. 使用OR操作符: 如果查詢條件中使用了OR連接不同字段,即使部分條件有索引,索引也可能不會使用。

    SELECT * FROM users WHERE last_name = 'Smith' OR age = 30;

    如果last_name有索引,而age沒有,last_name上的索引可能不會使用。

  2. 不符合最左前綴原則: 對於聯合索引,查詢條件必須包含聯合索引的最左邊列,否則索引可能失效。

    SELECT * FROM users WHERE age = 30;

    如果有一個聯合索引(last_name, age),這個查詢就不會使用索引。

  3. LIKE以通配符開頭: 如果使用LIKE操作符且模式以通配符'%'開頭,如LIKE '%abc',索引通常不會生效。

    SELECT * FROM users WHERE last_name LIKE '%abc';

    即使last_name上有索引,這種查詢也不會使用索引。

  4. 類型轉換: 如果查詢條件中對索引列進行了隱式的類型轉換,可能會導致索引失效。

    SELECT * FROM users WHERE age = '30';

    如果age是整數類型,這裏的字符串'30'需要進行類型轉換,可能會導致索引失效。

  5. 索引列進行計算或使用函數: 如果在查詢條件中對索引列使用了函數或進行了計算,索引可能會失效。

    SELECT * FROM users WHERE YEAR(birthdate) = 1990;

    如果birthdate字段有索引,使用YEAR函數可能會導致索引失效。

  6. 全表掃描更快時: 在某些情況下,即使有索引,MySQL優化器可能會選擇全表掃描,因爲它認爲這樣更快,尤其是在數據量較小的時候。

  7. 頻繁更新的字段: 經常更新的字段不適合作爲索引,因爲每次更新都會導致索引重新構建,這會消耗大量的資源。

  8. 索引選擇性差: 如果一個索引唯一性很差,即很多行都具有相同的索引值,那麼使用索引的效果將不明顯,因爲MySQL需要在這些具有相同索引值的行中進行進一步的查找。

  9. 使用了不等於操作符: 使用不等於(<>)操作符時,索引效果通常不如等值比較。

    SELECT * FROM users WHERE age <> 30;

    即使age字段有索引,這種查詢也可能不會使用索引。

  10. 複合索引未用左列字段: 在使用複合索引時,如果沒有使用到最左側的列,那麼整個複合索引都可能不會被使用。

    SELECT * FROM users WHERE age = 30;

    如果有一個複合索引(last_name, age),這個查詢就不會使用索引。

 

4.3.索引正確使用姿勢

在MySQL中,正確使用索引可以顯著提高查詢效率。以下是一些正確使用索引的SQL示例和最佳實踐:

  1. 創建和使用主鍵索引: 主鍵索引是唯一的,它確保了數據的唯一性,並且MySQL會自動爲主鍵創建索引。

    CREATE TABLE users ( id INT AUTO_INCREMENT, username VARCHAR(50), PRIMARY KEY (id) );
  2. 創建和使用唯一索引: 唯一索引保證列中的每一個值都是唯一的,這有助於加快查詢速度。

    CREATE UNIQUE INDEX idx_username ON users (username);
  3. 創建和使用普通索引: 普通索引(非唯一索引)可以幫助加速查找操作。

    CREATE INDEX idx_email ON users (email);
  4. 使用複合索引: 複合索引可以在多個列上創建,有助於多列條件的快速查詢。

    CREATE INDEX idx_name_age ON users (last_name, age);
  5. 避免使用OR操作符: 如果查詢條件中使用了OR連接不同字段,即使部分條件有索引,索引也可能不會使用。應儘量避免使用OR,或者將OR條件拆分成多個查詢。

  6. 避免在索引列上進行計算: 不要在索引列上使用函數或進行計算,這會導致索引失效。

  7. 使用LIMIT限制結果集: 使用LIMIT可以減少返回的數據量,這樣即使沒有索引,也能減少查詢時間。

  8. 選擇合適的索引類型: 根據存儲引擎的不同,選擇最合適的索引類型。例如,InnoDB存儲引擎使用B+Tree索引數據結構。

  9. 分析查詢語句: 使用EXPLAIN命令來分析查詢語句,確保索引被正確使用。

  10. 避免全表掃描: 儘量減少全表掃描的情況,因爲全表掃描會忽略索引,導致查詢效率降低。

 

4.4.提高查詢效率的重要優化策略

MySQL提高查詢效率的重要優化策略包括庫表結構優化、索引優化和查詢優化。以下是一些具體的優化措施:

  1. 庫表結構優化:
    • 避免使用SELECT *,只查詢需要的列,減少數據傳輸量。
    • 爲字段選擇合適的數據類型,以減少存儲空間並提高處理速度。
    • 合理設計表結構,避免過度複雜的關聯關係,以提高查詢效率。
  2. 索引優化:
    • 創建合適的索引,例如B樹索引或哈希索引,以提高查找速度。
    • 理解索引的工作原理,避免在大量重複值的列上創建索引,因爲這樣會導致索引效率降低。
    • 使用複合索引時,遵循最左前綴原則,即查詢條件應包含複合索引的最左側列。
  3. 查詢優化:
    • 使用EXPLAIN分析查詢語句,瞭解MySQL是如何處理語句的,從而進行查詢優化器的優化。
    • 避免在WHERE子句中使用函數或進行計算,因爲這會阻止使用索引。
    • 對於大數據集,考慮分頁查詢優化,但要注意LIMIT語句可能導致的性能問題。
    • 合理使用連接和子查詢,避免不必要的數據關聯和複雜的查詢結構。
    • 在適當的情況下,考慮使用索引覆蓋,這樣可以直接從索引中獲取所需數據,而無需訪問數據表的行。
      • 索引覆蓋指的是查詢所需的所有列都包含在索引中,因此不需要回表查詢數據行。這通常通過創建包含所有需要查詢字段的複合索引來實現。例如:

        •    
          創建一個包含name和age字段的複合索引。
          SQL查詢使用這兩個字段作爲過濾條件。
          CREATE TABLE user ( id INT PRIMARY KEY, name VARCHAR(20), age INT, INDEX name_age (name, age) ) ENGINE=InnoDB; SELECT id, name FROM user WHERE name = 'shenjian' AND age = 30;
          
          在這個例子中,如果EXPLAIN的結果中Extra字段顯示爲Using index,則表示觸發了索引覆蓋
    • 利用索引下推技術,儘早使用索引進行數據篩選,減少不必要的數據讀取。
      • 索引下推是MySQL 5.6引入的一個特性,它允許在查詢執行過程中,將過濾條件下推到存儲引擎層,減少“回表查詢”的次數。這意味着,即使某些記錄不滿足查詢條件,也可以在索引層被排除,而不是在所有記錄都被讀取之後。例如:
        • 假設有一個包含name、age和sex字段的表。
          SQL查詢使用了這三個字段作爲過濾條件。
          SELECT * FROM tuser WHERE name = 'zou' AND age = 10 AND sex = 1;
          這個查詢可以通過索引下推來優化,因爲即使某些記錄不滿足所有過濾條件,也可以在索引層被排除。

           

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章