分析MySQL中優化distinct的技巧

2022-10-06 01:39:10 字數 2198 閱讀 9717

有這樣的乙個需求:select count(distinct nick) from user_access_xx_xx;

這條sql用於統計使用者訪問的uv,由於單錶的資料量在10g以上,即使在user_access_xx_xx上加上nick的索引,

通過檢視執行計畫,也為全索引掃瞄,sql在執行的時候,會對整個伺服器帶來抖動;

root@db 09:00:12>select count(distinct nick) from user_access;

+———————-+

| count(distinct nick) |

+———————-+

程式設計客棧

| 8069 |

+———————-+

1 row in set (52.78 sec)

執行一次sql需要花費52.78s,已經非常的慢了

現在需要換一種思路來解決該問題:

我們知道索引的值是按照索引字段公升序的,比如我們對(nick,other_column)兩個欄位做了索引,那麼在索引中的則是按照nick,other_column的公升序排列:

我們現在的sql:select count(distinct nick) from user_access;則是直接從nick1開始一條條掃瞄下來,直到掃瞄到最後乙個nick_n,

那麼中間過程會掃瞄很多重複的nick,如果我們能夠跳過中間重複的nick,則效能會優化非常多(在oracle中,這種掃瞄技術為loose index ghswfqscan,但在5.1的版本中,mysql中還不能直接支援這種優化技術):

所以需要通過改寫sql來達到偽loose index scan:

root@db 09:41:30>select count(*) from ( select distinct(nick) from user_access)t ;

| count(*) |

+———-+

| 806934 |

1 row in set (5.81 sec)

s程式設計客棧ql中先選出不同的nick,最後在外面套一層,就可以得到nick的distinct值總和;

最重要的是在子查詢中:select distinct(nick) 實現了上圖中的偽loose index scan,優化器在這個時候的執行計畫為using index for group-by ,

需要注意的是mysql把distinct優化為group by,它首先利用索引來分組,然後掃瞄索引,對需要的nick只掃瞄一次;

兩個sql的執行計畫分別為:

優化寫法:

root@db 09:41:10>explain select distinct(nick) from user_access-> ;

+—-+————-+——————————+——-+—————+————-| id | select_type | table | type | possible_keys | key | key_len | ref | rows | extra |

+—-+————-+——————————+——-+—————+————-

| 1 | ****** | user_access | range | null | ind_user_access_nick | 67 | null | 2124695 | using index for group-by |

+—-+————-+——————————+——-+—————+————-

原始寫法:

root@db 09:42:55>explain select count(distinct nick) from user_access;

+—-+————-+——————————+——-+—————+————-

| id | select_type | table 程式設計客棧 | type | possible_keys | key | key_len | ref | rows | extra |

+—-+————-+——————————+——-+—————+————-

| 1 | ****** | user_access | index | null | ind_user_access | 177 | null | 19546123 | using index |

本文標題: 分析mysql中優化distinct的技巧

本文位址:

mysql優化案例分析

本文總結了一些工作常見的sql優化例子,雖然比較簡單,但很實用,希望對大家有所幫助。sql優化一般分為兩類,一類是sql本身的優化,如何走到合適的索引,如何減少排序,減少邏輯讀 另一類是sql本身沒有優化餘地,需要結合業務場景進行優化。即在滿足業務需求的情況下對sql進行改造,已提高sql執行速度,...

MySQL索引分析和優化

索引 索引用來快速地尋找那些具備特定值的記錄,任何mysql索引都以b 樹的形式儲存。假如沒有索引,執行查詢時mysql必須從第乙個記錄開始掃瞄整個表的任何記錄,直至找到符合需要的記錄。表裡面的記錄數量越多,這個操作的代價就越高。假如作為搜尋條件的列上已建立了索引,mysql無需掃瞄任何記錄即可迅速...

MySQL索引分析和優化

什麼是索引?索引用來快速地尋找那些具有特定值的記錄,所有mysql索引都以b 樹的形式儲存。如果沒有索引,執行查詢時mysql必須從第乙個記錄開始掃瞄整個表的所有記錄,直至找到符合要求的記錄。表裡面的記錄數量越多,這個操作的代價就越高。如果作為搜尋條件的列上已經建立了索引,mysql無需掃瞄任何記錄...