[英]Query slow when using order by in combination with a join
給出下表:
CREATE TABLE `webs_shoutbox` (
`shoutID` int(11) NOT NULL AUTO_INCREMENT,
`date` int(14) NOT NULL DEFAULT '0',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`message` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
PRIMARY KEY (`shoutID`),
KEY `shoutID` (`shoutID`),
KEY `name` (`name`(191))
) ENGINE=InnoDB AUTO_INCREMENT=62982 DEFAULT CHARSET=utf8 COLLATE=utf8_roman_ci |
CREATE TABLE `webs_user` (
`userID` int(11) NOT NULL AUTO_INCREMENT,
`registerdate` int(14) NOT NULL DEFAULT '0',
`lastlogin` int(14) NOT NULL DEFAULT '0',
`username` varchar(255) COLLATE utf8_roman_ci NOT NULL DEFAULT '',
`password` varchar(255) COLLATE utf8_roman_ci NOT NULL DEFAULT '',
`nickname` varchar(255) COLLATE utf8_roman_ci NOT NULL DEFAULT '',
....,
....,
PRIMARY KEY (`userID`),
KEY `nickname` (`nickname`),
KEY `userID` (`userID`)
) ENGINE=MyISAM AUTO_INCREMENT=3366 DEFAULT CHARSET=utf8 COLLATE=utf8_roman_ci
webs_user
表包含約4k條記錄, webs_shoutbox
包含約10萬條記錄。
我想使用left join
查詢數據庫並從兩個表中獲取數據:
select shoutID, date, name, message, webs_user.userID
from webs_shoutbox
left join webs_user on webs_shoutbox.name = webs_user.username
limit 10;
這將按預期方式運行,並且將很快返回結果(在ms范圍內)。 但是對於我的查詢,我需要按日期或shoutID進行排序,以獲取最新的查詢。 因此,我order by
聲明添加了一個order by
:
select shoutID, date, name, message, webs_user.userID
from webs_shoutbox
left join webs_user on webs_shoutbox.name = webs_user.username
order by shoutID desc
limit 10;
突然此查詢需要13-14秒!? 我真的對這個巨大的性能問題感到困惑。 經過大量的閱讀和谷歌搜索后,我無法找到為什么它在主鍵字段上進行如此可怕的排序。 當使用order by語句在webs_shoutbox
表上進行選擇時,它可以正常工作。 它只有在與組合join
了性能下降。
是什么原因造成的? 為什么花這么長時間才能進行看似快速的操作(按PK /索引排序)?
嘗試跟隨
SELECT ws.shoutID, ws.date, ws.name, ws.message, webs_user.userID FROM
(select shoutID, date, name, message
from webs_shoutbox
order by shoutID
limit 10) as ws
left join webs_user on ws.name = webs_user.username
order by shoutID desc limit 10
確保PK具有用於連接的哈希索引和用於排序的btree索引。
嘗試以下一種方法(我希望這種方法可行,因為將“ order by”限制為一張表):
select t1.shoutID, t1.date, t1.name, t1.message, webs_user.userID
from (
select *
from webs_shoutbox
order by order by shoutID desc
limit 10
) as t1
left join webs_user on t1.name = webs_user.username
order by shoutID desc
limit 10;
通常,最好不要將text / char / varchar字段用作關系方式(即外鍵)。 使用整數字段並為其建立索引會更快。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.