《Mysql實(shí)例在MySQL中使用STRAIGHT_JOIN的教程》要點(diǎn):
本文介紹了Mysql實(shí)例在MySQL中使用STRAIGHT_JOIN的教程,希望對(duì)您有用。如果有疑問(wèn),可以聯(lián)系我們。
MYSQL數(shù)據(jù)庫(kù)問(wèn)題
MYSQL數(shù)據(jù)庫(kù)?? 通過(guò)「SHOW FULL PROCESSLIST」語(yǔ)句很容易就能查到問(wèn)題SQL,如下:
MYSQL數(shù)據(jù)庫(kù)
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
MYSQL數(shù)據(jù)庫(kù)?? 說(shuō)明:因?yàn)閜ost和tag是多對(duì)多的關(guān)系,所以存在一個(gè)關(guān)聯(lián)表post_tag.
MYSQL數(shù)據(jù)庫(kù)?? 試著用EXPLAIN查詢(xún)一下SQL執(zhí)行計(jì)劃(篇幅所限,結(jié)果有刪減):
MYSQL數(shù)據(jù)庫(kù)
+----------+---------+-------+-----------------------------+
| table | key | rows | Extra |
+----------+---------+-------+-----------------------------+
| post_tag | tag_id | 71220 | Using where; Using filesort |
| post | PRIMARY | 1 | Using where |
+----------+---------+-------+-----------------------------+
MYSQL數(shù)據(jù)庫(kù)?? 下面給出優(yōu)化后的SQL,唯一的變化就是把連接方式改成了「STRAIGHT_JOIN」:
MYSQL數(shù)據(jù)庫(kù)
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
MYSQL數(shù)據(jù)庫(kù)?? 試著用EXPLAIN查詢(xún)一下SQL執(zhí)行計(jì)劃(篇幅所限,結(jié)果有刪減):
MYSQL數(shù)據(jù)庫(kù)
+----------+----------------+--------+-------------+
| table | key | rows | Extra |
+----------+----------------+--------+-------------+
| post | status_created | 119340 | Using where |
| post_tag | post_id | 1 | Using where |
+----------+----------------+--------+-------------+
MYSQL數(shù)據(jù)庫(kù)?? 對(duì)比優(yōu)化前后兩次EXPLAIN的結(jié)果來(lái)看,優(yōu)化后的SQL雖然「rows」更大了,但是沒(méi)有了「Using filesort」,綜合來(lái)看,性能依然得到了提升.
解釋
MYSQL數(shù)據(jù)庫(kù)?? 對(duì)第一條SQL而言,為什么MySQL優(yōu)化器選擇了一個(gè)耗時(shí)的執(zhí)行方案?對(duì)第二條SQL而言,為什么把連接方式改成STRAIGHT_JOIN之后就提升了性能?
MYSQL數(shù)據(jù)庫(kù)?? 這一切還得從MySQL對(duì)多表連接的處理方式說(shuō)起,首先要確定以誰(shuí)為驅(qū)動(dòng)表,也就是說(shuō)以哪個(gè)表為基準(zhǔn),在處理此類(lèi)問(wèn)題時(shí),MySQL優(yōu)化器采用了簡(jiǎn)單粗暴的解決方法:哪個(gè)表的結(jié)果集小,就以哪個(gè)表為驅(qū)動(dòng)表,通常這都是最佳選擇.
MYSQL數(shù)據(jù)庫(kù)?? 說(shuō)明:在EXPLAIN結(jié)果中,第一行出現(xiàn)的表就是驅(qū)動(dòng)表.
MYSQL數(shù)據(jù)庫(kù)?? 繼續(xù)post連接post_tag的例子,MySQL優(yōu)化器有如下兩個(gè)選擇,分別是:
MYSQL數(shù)據(jù)庫(kù)?????? 顯而易見(jiàn),post_tag過(guò)濾的結(jié)果集更小,所以MySQL優(yōu)化器選擇它作為驅(qū)動(dòng)表,可悲催的是我們還需要以post表中的created字段來(lái)排序,也就是說(shuō)排序字段不在驅(qū)動(dòng)表里,于是乎不可避免的出現(xiàn)了「Using filesort」,從而導(dǎo)致慢查詢(xún).
MYSQL數(shù)據(jù)庫(kù)?????? 知道了來(lái)龍去脈,優(yōu)化起來(lái)就容易了.頭等大事是務(wù)必保證排序字段在驅(qū)動(dòng)表中,所以必須以post是驅(qū)動(dòng)表,于是乎「STRAIGHT_JOIN」就成了答案,它強(qiáng)制了連接順序.
MYSQL數(shù)據(jù)庫(kù)?????? …
MYSQL數(shù)據(jù)庫(kù)?????? 不過(guò)我總覺(jué)得「STRAIGHT_JOIN」這種非標(biāo)準(zhǔn)的語(yǔ)法屬于奇技淫巧的范疇,能不用盡量不用,畢竟多數(shù)情況下,MySQL優(yōu)化器都能做出正確的選擇.
轉(zhuǎn)載請(qǐng)注明本頁(yè)網(wǎng)址:
http://www.fzlkiss.com/jiaocheng/3450.html