mysql - 使用 ORDER BY 对结果进行排序时,LEFT JOIN 花费的时间太长

标签 mysql sql-order-by left-join

这是我在 stackoverflow 中的第一个问题,通常我习惯在互联网上搜索答案,但这次我找不到这个问题的任何答案。

我的问题是查询执行时间太长,而它是两个表之间的简单联接

我将首先发布我的查询,然后我将发布有关我的系统的更多详细信息:

SELECT * FROM tbl_item 
LEFT JOIN (SELECT * FROM tbl_item_details) AS tbl_item_details 
ON tbl_item.item_id = tbl_item_details.item_details_item_id 
WHERE item_active = 1 ORDER BY item_views DESC LIMIT 0,5

这是我的表格结构:

CREATE TABLE `tbl_item` (
`item_id` int(11) NOT NULL AUTO_INCREMENT,
`item_views` int(11) NOT NULL,
`item_active` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`item_id`)
) ENGINE=InnoDB AUTO_INCREMENT=821 DEFAULT CHARSET=utf8

tbl_item_details:

CREATE TABLE `tbl_item_details` (
`item_details_id` int(11) NOT NULL AUTO_INCREMENT,
`item_details_title` varchar(255) NOT NULL,
`item_details_content` longtext NOT NULL,
`item_details_item_id` int(11) NOT NULL,
PRIMARY KEY (`item_details_id`),
KEY `itm_dt_itm_id` (`item_details_item_id`),
CONSTRAINT `tbl_item_details_ibfk_1` FOREIGN KEY (`itm_dt_itm_id`) REFERENCES `tbl_item` (`itm_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=364 DEFAULT CHARSET=utf8

这里是 EXPLAIN 查询输出:

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   PRIMARY     tbl_item    ALL     NULL    NULL    NULL    NULL    358     Using where; Using temporary; Using filesort
1   PRIMARY       ALL     NULL    NULL    NULL    NULL    358      
2   DERIVED     tbl_item_details    ALL     NULL    NULL    NULL    NULL    422      

每个表只有 350 行,而大表 (tbl_item_details) 为 1.5 MB,因此您会看到表非常小。

基本上,上述查询在以下系统上执行大约需要 4 秒:

CPU:Intel(R) Pentium(R) 4 CPU 3.20GHz(2 个 CPU),~3.2GHz 内存:3 GB Mysql:5.1.33(包含在 wamp 中)

之前,任何人都在这里提出了一个解决方案,这是我尝试过的,什么有效,什么无效:

有效的方法和查询花费的时间要少得多(0.06 秒):

  • 我尝试删除 ORDER BY 我尝试删除 item_details_content
  • 我尝试使用 INNER JOIN 进行选择,并且我尝试过它有效
  • 切换连接中的表,使 INNER 表变为 OUTER 表,反之亦然

我不能使用 INNER JOIN,因为 tbl_item 中可能有一些行在 tbl_item_details 中没有匹配项,而我想要这些记录

我尝试过但不起作用的事情:

  • 我尝试向 item_views 添加索引(不起作用)
  • 我尝试删除外键约束
  • 我尝试将表引擎切换为 MyIsam

显然,当 mysql 对日期进行排序并面对 item_details_content 中的(相对)大数据时,就会出现问题,因此,如果我们去掉其中一项(排序或 item_details_content 列),它就可以正常工作。

但事实是,这种事不应该发生!因为该表的数据确实非常小,因为它只有 350 行,总共 1.5 MB! mysql 应该能够处理比这更多的数据。

请在建议对查询结构进行大幅更改之前,恐怕这是不可能的,因为我已经在这个框架上工作了一段时间并且查询是动态生成的,对查询的更改可能意味着几天工作量很大,但我们随时欢迎您提出建议。

P.S:我在强大的服务器(核心 i7 和 8 GB RAM)上尝试了这个查询,花费了 0.3 秒,这对于这样的数据库来说仍然太长

感谢一百万

最佳答案

你尝试过吗:

SELECT * FROM tbl_item 
LEFT JOIN tbl_item_details 
ON tbl_item.item_id = tbl_item_details.item_details_item_id 
WHERE item_active = 1 ORDER BY item_views DESC LIMIT 0,5

我真的不认为你需要只从 tbl_item_details 中选择 * 的嵌套子查询——只需使用表。

关于mysql - 使用 ORDER BY 对结果进行排序时,LEFT JOIN 花费的时间太长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10109218/

相关文章:

php - ORDER BY 时间戳 < 24 小时的记录数量 (MySQL)

mysql 按日期排序得到 10 个结果然后再次按 id 排序

sql - 排序查询结果太慢

mysql - 等于此右连接的左连接是什么?

mysql - 选择 MySQL Month() 作为空列

php - 指定具有根类别和子类别的数组

mysql - SQL varchar 字符限制

mysql - 删除表中 TimeStamp 最小的地方

MySQL:在表列和 group_concat 中使用逗号分隔的 id

sql - 嵌套左连接和合并的问题