在MySQL中使用STRAIGHT_JOIN的教程
問題
通過「SHOW FULL PROCESSLIST」語句很容易就能查到問題SQL,如下:
SELECT post.* FROM post INNER JOIN post_tag ON post.id = post_tag.post_id WHERE post.status = 1 AND post_tag.tag_id = 123 ORDER BY post.created DESC LIMIT 100
說明:因?yàn)閜ost和tag是多對多的關(guān)系,所以存在一個(gè)關(guān)聯(lián)表post_tag。
試著用EXPLAIN查詢一下SQL執(zhí)行計(jì)劃(篇幅所限,結(jié)果有刪減):
+----------+---------+-------+-----------------------------+ | table | key | rows | Extra | +----------+---------+-------+-----------------------------+ | post_tag | tag_id | 71220 | Using where; Using filesort | | post | PRIMARY | 1 | Using where | +----------+---------+-------+-----------------------------+
下面給出優(yōu)化后的SQL,唯一的變化就是把連接方式改成了「STRAIGHT_JOIN」:
SELECT post.* FROM post STRAIGHT_JOIN post_tag ON post.id = post_tag.post_id WHERE post.status = 1 AND post_tag.tag_id = 123 ORDER BY post.created DESC LIMIT 100
試著用EXPLAIN查詢一下SQL執(zhí)行計(jì)劃(篇幅所限,結(jié)果有刪減):
+----------+----------------+--------+-------------+ | table | key | rows | Extra | +----------+----------------+--------+-------------+ | post | status_created | 119340 | Using where | | post_tag | post_id | 1 | Using where | +----------+----------------+--------+-------------+
對比優(yōu)化前后兩次EXPLAIN的結(jié)果來看,優(yōu)化后的SQL雖然「rows」更大了,但是沒有了「Using filesort」,綜合來看,性能依然得到了提升。
解釋
對第一條SQL而言,為什么MySQL優(yōu)化器選擇了一個(gè)耗時(shí)的執(zhí)行方案?對第二條SQL而言,為什么把連接方式改成STRAIGHT_JOIN之后就提升了性能?
這一切還得從MySQL對多表連接的處理方式說起,首先要確定以誰為驅(qū)動(dòng)表,也就是說以哪個(gè)表為基準(zhǔn),在處理此類問題時(shí),MySQL優(yōu)化器采用了簡單粗暴的解決方法:哪個(gè)表的結(jié)果集小,就以哪個(gè)表為驅(qū)動(dòng)表,通常這都是最佳選擇。
說明:在EXPLAIN結(jié)果中,第一行出現(xiàn)的表就是驅(qū)動(dòng)表。
繼續(xù)post連接post_tag的例子,MySQL優(yōu)化器有如下兩個(gè)選擇,分別是:
- 以post為驅(qū)動(dòng)表,通過status_created索引過濾,結(jié)果集119340行
- 以post_tag為驅(qū)動(dòng)表,通過tag_id索引過濾,結(jié)果集71220行
顯而易見,post_tag過濾的結(jié)果集更小,所以MySQL優(yōu)化器選擇它作為驅(qū)動(dòng)表,可悲催的是我們還需要以post表中的created字段來排序,也就是說排序字段不在驅(qū)動(dòng)表里,于是乎不可避免的出現(xiàn)了「Using filesort」,從而導(dǎo)致慢查詢。
知道了來龍去脈,優(yōu)化起來就容易了。頭等大事是務(wù)必保證排序字段在驅(qū)動(dòng)表中,所以必須以post是驅(qū)動(dòng)表,于是乎「STRAIGHT_JOIN」就成了答案,它強(qiáng)制了連接順序。
…
不過我總覺得「STRAIGHT_JOIN」這種非標(biāo)準(zhǔn)的語法屬于奇技淫巧的范疇,能不用盡量不用,畢竟多數(shù)情況下,MySQL優(yōu)化器都能做出正確的選擇。
相關(guān)文章
mysql使用SQLyog導(dǎo)入csv數(shù)據(jù)不成功的解決方法
給mysql導(dǎo)入數(shù)據(jù),選中某個(gè)表選擇導(dǎo)入--導(dǎo)入使用本地csv數(shù)據(jù)即可,單有的時(shí)候不知道什么問題導(dǎo)入不成功2014-07-07
Ubuntu 18.04下mysql 8.0 安裝配置方法圖文教程
這篇文章主要為大家詳細(xì)介紹了Ubuntu 18.04下mysql 8.0 安裝配置方法圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05
windows server2014 安裝 Mysql Applying Security出錯(cuò)的完美解決方法
這篇文章給大家介紹了windows server2014 安裝 Mysql Applying Security出錯(cuò)的完美解決方法,造成這種問題的主要原因是因?yàn)榘惭b一遍之后沒有卸載干凈,要解決這個(gè)問題需要注意以下幾點(diǎn),具體解決方法,大家參考下本文2017-07-07
Centos7使用yum安裝Mysql5.7.19的詳細(xì)步驟
本篇文章主要介紹了Centos7使用yum安裝Mysql5.7.19的詳細(xì)步驟,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09
mysql 8.0.18 安裝配置方法圖文教程(linux)
這篇文章主要介紹了linux下mysql 8.0.18 安裝配置方法圖文教程,文中安裝步驟介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11

