這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)碛嘘P(guān)如何解決工作中遇到的SQL優(yōu)化,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、小程序開發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了鄂爾多斯免費(fèi)建站歡迎大家使用!
-- 示例表 CREATE TABLE `employees` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(24) NOT NULL DEFAULT '' COMMENT '姓名', `age` int(20) NOT NULL DEFAULT '0' COMMENT '年齡', `position` varchar(20) NOT NULL DEFAULT '' COMMENT '職位', `hire_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '入職時(shí)間', PRIMARY KEY (`id`), KEY `idx_name_age_position` (`name`,`age`,`position`) USING BTREE, KEY `idx_age` (`age`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=136326 DEFAULT CHARSET=utf8 COMMENT='員工表'
EXPLAIN select * from employees WHERE name='LiLei' and position='dev' order by age;
利用最左前綴法則:中間字段不能斷,因此查詢用到了name索引,從key_len=74也能看出,age索引列用在排序的過程中,因?yàn)镋xtra字段里沒有using filesort。
EXPLAIN select * from employees WHERE name='LiLei' order by position;
從explain的執(zhí)行結(jié)果來看:key_len=74, 查詢使用name索引,由于用了position進(jìn)行排序,跳過了age,出現(xiàn)了Using filesort。
EXPLAIN select * from employees WHERE name='LiLei' order by age,position;
查找只用到了name索引,age和position用于排序,無Using filesort。
EXPLAIN select * from employees WHERE name='LiLei' order by position,age;
和上一個(gè)case不同的是,Extra中出現(xiàn)了Using filesort,因?yàn)樗饕膭?chuàng)建順序?yàn)閚ame,age,position,但是排序的時(shí)候age和position顛倒了位置。
EXPLAIN select * from employees WHERE name='LiLei' order by age asc, position desc;
雖然排序的字段和聯(lián)合索引順序是一樣的,且order by是默認(rèn)升序,這里position desc是降序,導(dǎo)致與索引的排序方式不同,從而產(chǎn)生Using filesort。MySQL8以上版本有降序索引可以支持該種查詢方式。
EXPLAIN select * from employees WHERE name in('LiLei', 'zhuge') order by age, position ;
對于排序來說,多個(gè)相等條件也是范圍查詢。
EXPLAIN select * from employees WHERE name > 'a' order by name;
可以用覆蓋索引優(yōu)化
EXPLAIN select name,age,position from employees WHERE name > 'a' order by name;
EXPLAIN select * from employees where name='LiLei' order by position;
查看這條sql對應(yīng)trace結(jié)果(只展示排序部分):
set session optimizer_trace="enabled=on",end_markers_in_json=on; ‐‐開啟trace select * from employees where name = 'LiLei' order by position; select * from information_schema.OPTIMIZER_TRACE; { "join_execution": { --sql執(zhí)行階段 "select#": 1, "steps": [ { "filesort_information": [ { "direction": "asc", "table": "`employees`", "field": "position" } ] /* filesort_information */, "filesort_priority_queue_optimization": { "usable": false, "cause": "not applicable (no LIMIT)" } /* filesort_priority_queue_optimization */, "filesort_execution": [ ] /* filesort_execution */, "filesort_summary": { --文件排序信息 "rows": 1, --預(yù)計(jì)掃描行數(shù) "examined_rows": 1, --參與排序的行 "number_of_tmp_files": 0, --使用臨時(shí)文件的個(gè)數(shù),這個(gè)值為0代表全部使用sort_buffer內(nèi)存排序,否則使用磁盤文件排序 "sort_buffer_size": 200704, --排序緩存的大小 "sort_mode": "" --排序方式,這里用的單路排序 } /* filesort_summary */ } ] /* steps */ } /* join_execution */ }
修改max_length_for_sort_data=10
set max_length_for_sort_data = 10; --employees表所有字段長度總和肯定大于10字節(jié) select * from employees where name = 'LiLei' order by position; select * from information_schema.OPTIMIZER_TRACE; { "join_execution": { "select#": 1, "steps": [ { "filesort_information": [ { "direction": "asc", "table": "`employees`", "field": "position" } ] /* filesort_information */, "filesort_priority_queue_optimization": { "usable": false, "cause": "not applicable (no LIMIT)" } /* filesort_priority_queue_optimization */, "filesort_execution": [ ] /* filesort_execution */, "filesort_summary": { "rows": 1, "examined_rows": 1, "number_of_tmp_files": 0, "sort_buffer_size": 53248, "sort_mode": "" --排序方式為雙路排序 } /* filesort_summary */ } ] /* steps */ } /* join_execution */ }
對比這兩個(gè)排序模式,單路排序會(huì)把所有的需要查詢的字段數(shù)據(jù)都放到sort_buffer中,而雙路排序只會(huì)把主鍵id和需要排序的字段放到sort_buffer中進(jìn)行排序,然后再通過主鍵id 回到原表 查詢需要的字段數(shù)據(jù)。MySQL通過max_length_for_sort_data這個(gè)參數(shù)來控制排序,在不同場景下使用不同的排序模式,從而提升排序效率。
Mysql支持兩種方式的排序filesort和index,using index是指Mysql掃描索引本身完成排序。index效率高,filesort效率低。
order by滿足兩種情況會(huì)使用using index。 order by語句使用索引最左前列。 使用where子句和order by子句 條件列組合滿足索引最左前列。
盡量在索引列上完成排序,遵循索引建立(索引創(chuàng)建的順序)時(shí)候的最左前綴法則。
如果order by 的條件不在索引列上,就會(huì)產(chǎn)生using filesort。
上述就是小編為大家分享的如何解決工作中遇到的SQL優(yōu)化了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。