1. 程式人生 > 其它 >mysql索引注意事項

mysql索引注意事項

MySQL 索引通常是被用於提高 WHERE 條件的資料行匹配時的搜尋速度,在索引的使用過程中,存在一些使用細節和注意事項。

函式,運算,否定操作符,連線條件,多個單列索引,最左字首原則,範圍查詢,不會包含有NULL值的列,like 語句不要在列上使用函式和進行運算

1)不要在列上使用函式,這將導致索引失效而進行全表掃描。

select * from news where year(publish_time) < 2017

為了使用索引,防止執行全表掃描,可以進行改造。

select * from news where publish_time < '2017-01-01'

還有一個建議,不要在列上進行運算,這也將導致索引失效而進行全表掃描。

select * from news where id / 100 = 1

為了使用索引,防止執行全表掃描,可以進行改造。

select * from news where id = 1 * 100

2)儘量避免使用 != 或 not in或 <> 等否定操作符

應該儘量避免在 where 子句中使用 != 或 not in 或 <> 操作符,因為這幾個操作符都會導致索引失效而進行全表掃描。儘量避免使用 or 來連線條件 應該儘量避免在 where 子句中使用 or 來連線條件,因為這會導致索引失效而進行全表掃描。

select * from news where id = 1 or id = 2

3)多個單列索引並不是最佳選擇 MySQL 只能使用一個索引

會從多個索引中選擇一個限制最為嚴格的索引,因此,為多個列建立單列索引,並不能提高 MySQL 的查詢效能。 假設,有兩個單列索引,分別為 news_year_idx(news_year) 和 news_month_idx(news_month)。現在,有一個場景需要針對資訊的年份和月份進行查詢,那麼,SQL 語句可以寫成:

select * from news where news_year = 2017 and news_month = 1

事實上,MySQL 只能使用一個單列索引。為了提高效能,可以使用複合索引 news_year_month_idx(news_year, news_month) 保證 news_year 和 news_month 兩個列都被索引覆蓋。

4)複合索引的最左字首原則 複合索引遵守“最左字首”原則

即在查詢條件中使用了複合索引的第一個欄位,索引才會被使用。因此,在複合索引中索引列的順序至關重要。如果不是按照索引的最左列開始查詢,則無法使用索引。 假設,有一個場景只需要針對資訊的月份進行查詢,那麼,SQL 語句可以寫成:

select * from news where news_month = 1

此時,無法使用 news_year_month_idx(news_year, news_month) 索引,因為遵守“最左字首”原則,在查詢條件中沒有使用複合索引的第一個欄位,索引是不會被使用的。

5)覆蓋索引的好處 如果一個索引包含所有需要的查詢的欄位的值

直接根據索引的查詢結果返回資料,而無需讀表,能夠極大的提高效能。因此,可以定義一個讓索引包含的額外的列,即使這個列對於索引而言是無用的。

6)範圍查詢對多列查詢的影響 查詢中的某個列有範圍查詢

則其右邊所有列都無法使用索引優化查詢。 舉個例子,假設有一個場景需要查詢本週釋出的資訊文章,其中的條件是必須是啟用狀態,且釋出時間在這周內。那麼,SQL 語句可以寫成:

select * from news where publish_time >= '2017-01-02' and publish_time <= '2017-01-08' and enable = 1

這種情況下,因為範圍查詢對多列查詢的影響,將導致 news_publish_idx(publish_time, enable) 索引中 publish_time 右邊所有列都無法使用索引優化查詢。換句話說,news_publish_idx(publish_time, enable) 索引等價於 news_publish_idx(publish_time) 。 對於這種情況,我的建議:對於範圍查詢,務必要注意它帶來的副作用,並且儘量少用範圍查詢,可以通過曲線救國的方式滿足業務場景。 例如,上面案例的需求是查詢本週釋出的資訊文章,因此可以建立一個news_weekth 欄位用來儲存資訊文章的周資訊,使得範圍查詢變成普通的查詢,SQL 可以改寫成:

select * from news where news_weekth = 1 and enable = 1

然而,並不是所有的範圍查詢都可以進行改造,對於必須使用範圍查詢但無法改造的情況,我的建議:不必試圖用 SQL 來解決所有問題,可以使用其他資料儲存技術控制時間軸,例如 Redis 的 SortedSet 有序集合儲存時間,或者通過快取方式快取查詢結果從而提高效能。 7)索引不會包含有NULL值的列 只要列中包含有 NULL 值都將不會被包含在索引中,複合索引中只要有一列含有 NULL值,那麼這一列對於此複合索引就是無效的。 因此,在資料庫設計時,除非有一個很特別的原因使用 NULL 值,不然儘量不要讓欄位的預設值為 NULL。 8)隱式轉換的影響 當查詢條件左右兩側型別不匹配的時候會發生隱式轉換,隱式轉換帶來的影響就是可能導致索引失效而進行全表掃描。下面的案例中,date_str 是字串,然而匹配的是整數型別,從而發生隱式轉換。

select * from news where date_str = 201701

因此,要謹記隱式轉換的危害,時刻注意通過同類型進行比較。 9)like 語句的索引失效問題 like 的方式進行查詢,在 like “value%” 可以使用索引,但是對於 like “%value%” 這樣的方式,執行全表查詢,這在資料量小的表,不存在效能問題,但是對於海量資料,全表掃描是非常可怕的事情。所以,根據業務需求,考慮使用 ElasticSearch 或 Solr 是個不錯的方案。

學向勤中得,螢窗萬卷書。