在數據庫運維過程當中,優化 SQL 是 DBA 團隊的平常任務。例行 SQL 優化,不只能夠提高程序性能,還可以下降線上故障的機率。mysql
目前經常使用的 SQL 優化方式包括但不限於:業務層優化、SQL邏輯優化、索引優化等。其中索引優化一般經過調整索引或新增索引從而達到 SQL 優化的目的。索引優化每每能夠在短期內產生很是巨大的效果。若是可以將索引優化轉化成工具化、標準化的流程,減小人工介入的工做量,無疑會大大提升DBA的工做效率。git
SQLAdvisor 是由美團點評公司北京DBA團隊開發維護的 SQL 優化工具:輸入SQL,輸出索引優化建議。 它基於 MySQL 原生詞法解析,再結合 SQL 中的 where 條件以及字段選擇度、聚合條件、多表 Join 關係等最終輸出最優的索引優化建議。目前 SQLAdvisor 在公司內部大量使用,較爲成熟、穩定。github
如今,咱們很是高興地將 SQLAdvisor 開源,項目 GitHub 地址:https://github.com/Meituan-Dianping/SQLAdvisor 。咱們已經把相關開發工做全面轉到 GitHub 上,開源版本和內部使用版本保持徹底一致。但願與業內有相似需求的團隊,一塊兒打造一款優秀的 SQL 優化產品。sql
SQLAdvisor架構流程圖:數據庫
1
2
3
4
|
sql: SELECT id FROM crm_loan WHERE id_card = '1234567'
cmd: ./sqladvisor -h xx -P xx -u xx -pxx -d xx -q "SELECT id FROM crm_loan WHERE id_card = '1234567'"
SQLAdvisor輸出: alter table crm_loan add index idx_id_card(id_card)
|
上述實現時,涉及的函數爲:mysql_sql_parse_join(TABLE_LIST join_table) mysql_sql_parse_join(Item join_condition) ,主要流程圖以下:運維
- offset = (table_count / 2) > 10W ? 10W : (table_count / 2)
- rand_rows =(table_count / 2) > 1W ? 1W : (table_count / 2)
- 使用select count(1) from (select field from table force index(best_index) order by cl.. desc limit rand_rows) where field_print 獲得知足條件的rows。
- cardinality = rows == 0 ? rand_rows : rand_rows / rows;
- 計算完成選擇度後,會根據選擇度大小,將該條件添加到該表中的備選索引中。
主要涉及的函數爲:mysql_sql_parse_field_cardinality_new() 計算選擇度。ide
- 涉及到的字段必須來自於同一張表,而且這張表必須是肯定下來的驅動表。
- Group by 優於 Order by, 二者只能同時存在一個。
- Order by 字段的排序方向必須徹底一致,不然丟棄整個 Order by 字段列。
- 當 Order by 條件中包含主鍵時,若是主鍵字段爲 Order by。 字段列末尾,忽略該主鍵,不然丟棄整個 Order by 字段列。
- mysql_sql_parse_group() 判斷 Group 後的字段是否均來自於同一張表。
- mysql_sql_parse_order() 判斷 Order 後的條件是否可使用。
- mysql_sql_parse_group_order_add() 將字段依次按照規則添加到備選索引鏈表中。