簡體   English   中英

通過結合使用訂單時查詢緩慢

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM