Mysql 使用ORDER BY对结果进行排序时,左联接花费的时间太长

Mysql 使用ORDER BY对结果进行排序时,左联接花费的时间太长,mysql,sql-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

这是我在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
待定项目详情:

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
下面是解释查询输出:

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_详细信息为1.5MB,因此您可以看到这些表非常小

基本上,在以下系统上执行上述查询几乎需要4秒钟:

CPU:IntelR PentiumR 4 CPU 3.20GHz 2 CPU,~3.2GHz 内存:3 GB Mysql:5.1.33包含在wamp中

在此之前,有人建议解决方案是我尝试过的,有效的和无效的:

有效的操作和查询花费的时间要少得多0.06秒:

我试图通过从中删除项目\详细信息\内容来删除订单 我尝试使用内部联接来替代选择,但我尝试了 切换联接中的表,使内部表变为外部表,反之亦然 我无法使用内部联接,因为tbl_项目中可能有行在tbl_项目详细信息中没有匹配项,我需要这些记录

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

我尝试向项目视图添加索引,但没有成功 我尝试删除外键约束 我试着把桌子引擎切换到MyIsam 很明显,当mysql对日期进行排序并且在item\u details\u内容中面对相对较大的数据时,就会出现问题,因此,如果我们去掉排序或列item\u details\u内容中的一个内容,它就可以正常工作

但问题是,这不应该发生!因为这个表的数据非常小,因为它只有350行,总共1.5MB!mysql应该能够处理更多的数据

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

附言:我在一个功能强大的服务器核心i7和8gbram上尝试了这个查询,花了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中选择*的嵌套子查询-只需使用该表即可。

抱歉,我要说的是一个简短的提示:我认为问题在于您没有进行简单的联接,因为您是在子查询上联接的。该查询的结果集没有索引,因为它是动态创建的。只有具有索引的表上的联接!你很快。请在TBLIITEMIX细节上加入,而不是选择该表。请考虑将索引添加到列TBLIITITMS.ITEMY视图中。这应该会提高查询性能。Nanne,谢谢你的回答,但是连接表上的条件如何呢?实际上,第一个表中的每一行应该有两行或更多行,每种语言对应一行。那么,像tbl_item.item_id=tbl_item_details.item_details_item_id和tbl_item_details.item_language=VALUE这样做是否安全呢?正如我在前面的问题中提到的,我不确定你说的索引是什么意思,你是指我正在排序的字段吗!因为是的,我尝试了一个索引,它没有改变任何东西,或者如果你的意思是我在第二个表中没有索引,那么是的,它有一个索引,它也有一个主键,我不是假设你的意思是我应该在项目_details _contentfield上添加全文索引啊,我只是想添加一个索引,但是我忘记了,将字段声明为主键会隐式地索引该字段,所以不必担心索引。删除子查询有帮助吗?@Al-Kateb最后一件事。。。如果您的应用程序没有很多并发用户同时更新表中的不同行,那么您可能应该在引擎中尝试MyISAM,而不是InnoDB。这里有一点关于差异的说明,但据我所知,InnoDB使用行锁定和表锁定,而且CPU的效率也较低。谢谢你的建议,我太依赖外键约束了,但是消除子查询肯定有帮助,我正在用PHP构建一个framkework,所以当我第一次决定加入子查询时,我想在子查询中加入where条件,我不知道这会对性能造成太大影响,所以我要把它移到桌子上,因为这不值得。谢谢大家的回答啊,是的,fk限制有点像密萨姆的想法。也许您可以有一个将数据插入临时表的存储过程,这样您就不需要子查询,也不知道这对您的数据是否有意义。 实际上,我有点惊讶它对查询的影响如此之大——我以前使用过连接子查询,只是我通常在where子句中使用它们,而不是在连接部分中使用它们,这可能就是原因。无论如何,祝你好运。