美團點評SQL優化工具SQLAdvisor開源

2021-10-07 18:17:08 字數 3842 閱讀 4535

在資料庫運維過程中,優化 sql 是 dba 團隊的日常任務。例行 sql 優化,不僅可以提公升程式效能,還能夠降低線上故障的概率。

目前常用的 sql 優化方式包括但不限於:業務層優化、sql邏輯優化、索引優化等。其中索引優化通常通過調整索引或新增索引從而達到 sql 優化的目的。索引優化往往可以在短時間內產生非常巨大的效果。如果能夠將索引優化轉化成工具化、標準化的流程,減少人工介入的工作量,無疑會大大提高dba的工作效率。

sqladvisor 是由美團點評公司北京dba團隊開發維護的 sql 優化工具:輸入sql,輸出索引優化建議。 它基於 mysql 原生詞法解析,再結合 sql 中的 where 條件以及字段選擇度、聚合條件、多表 join 關係等最終輸出最優的索引優化建議。目前 sqladvisor 在公司內部大量使用,較為成熟、穩定。

sqladvisor架構流程圖

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)

sqladvisor快速入門教程

join語法分為兩種:join on 和 join using,並且 join on 有時會存在 where 條件中。

分析 join 條件首先會得到乙個 nested_join 的 table list,通過判斷它的 join_using_fields 字段是否為空來區分 join on 與 join using。

生成的 table list 以二叉樹的形式進行儲存,以後序遍歷的方式對二叉樹進行遍歷。

生成內部解析樹時,right join 會轉換成 left join。

join 條件會存在當層的葉子節點上,如果左右節點都是葉子節點,會存在右葉子節點。

每乙個非葉子節點代表一次 join 的結果。

上述實現時,涉及的函式為:mysql_sql_parse_join(table_list *join_table) mysql_sql_parse_join(item *join_condition) ,主要流程圖如下:

主要是提取 sql 語句的 where 條件。where 條件中一般由 and 和 or 連線符進行連線,因為 or 比較難以處理,所以忽略,只處理 and 連線符。

由於 where 條件中可以存在 join 條件,因此需要進行區分。

依次獲取 where 條件,當條件中的操作符是 like,如果不是字首匹配則丟棄這個條件。

根據條件計算欄位的區分度按照高低進行倒序排,如果小於30則丟棄。同時使用最左原則將 where 條件進行有序排列。

通過 「show table status like」 獲得表的總行數 table_count。

通過計算選擇表中已存在的區分度最高的索引 best_index,同時primary key > unique key > 一般索引。

通過計算獲取資料取樣的起始值offset與取樣範圍rand_rows: > * 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() 計算選擇度。

mysql_sql_parse_index()將條件按照選擇度新增到備選索引鍊錶中。

上述兩函式的流程圖如下所示:

group 欄位與 order 字段能否用上索引,需要滿足如下條件: > * 涉及到的字段必須來自於同一張表,並且這張表必須是確定下來的驅動表。 > * group by 優於 order by, 兩者只能同時存在乙個。 > * order by 欄位的排序方向必須完全一致,否則丟棄整個 order by 欄位列。 > * 當 order by 條件中包含主鍵時,如果主鍵欄位為 order by。 欄位列末尾,忽略該主鍵,否則丟棄整個 order by 欄位列。

整個索引列排序優先順序:等值》(group by | order by )> 非等值。

該過程中設計的函式主要有: > * mysql_sql_parse_group() 判斷 group 後的字段是否均來自於同一張表。 > * mysql_sql_parse_order() 判斷 order 後的條件是否可以使用。 > * mysql_sql_parse_group_order_add() 將字段依次按照規則新增到備選索引鍊錶中。

經過前期的 where 解析、join 解析,已經將 sql 中表關聯關係儲存起來,並且按照一定邏輯將候選驅動表確定下來。

在侯選驅動表中,按照每一張表的侯選索引欄位中第乙個字段進行計算表中結果集大小。

使用 explain select * from table where field 來計算表中結果集。

結果集小最小的被確為驅動表。

步驟中涉及的函式為:final_table_drived(),在該函式中,呼叫了函式 get_join_table_result_set() 來獲取每張驅動候選表的行數。

通過上述過程,已經選擇了驅動表,也通過解析儲存了語句中的條件。

由於選定了驅動表,因此需要對被驅動表的索引,根據 join 條件進行新增。

該過程涉及的函式主要是:mysql_index_add_condition_field(),流程如下:

通過上述步驟,已經將每張表的備選索引鍵全部儲存。此時,只要判斷每張表中的候選索引鍵是否在實際表中已存在。沒有索引,則給出建議增加對應的索引。

該步驟涉及的函式是:print_index() ,主要的流程圖為:

bugs fixed

sqladvisor快速入門教程.

sqladvisor原理和架構.

sqladvisor release notes.

sqladvisor開發規範.

faq.

美團SQL優化工具SQLAdvisor

介紹 美團sql優化工具sqladvisor 1 sqladvisor安裝 拉取最新 git clone 安裝依賴項 yum install y apt get install cmake libaio devel libffi devel glib2 glib2 devel yum install...

美團SQL優化工具SQLAdvisor

在資料庫運維過程中,優化 sql 是 dba 團隊的日常任務。例行 sql 優化,不僅可以提公升程式效能,還能夠降低線上故障的概率。目前常用的 sql 優化方式包括但不限於 業務層優化 sql邏輯優化 索引優化等。其中索引優化通常通過調整索引或新增索引從而達到 sql 優化的目的。索引優化往往可以在...

sqladvisor 點評sql語句優化工具

安裝方法 安裝依賴包 yum y install cmake libaio devel libffi devel glib2 glib2 devel yum install yum y install percona server shared 56 cd usr lib64 ln s libper...