Mysql 复杂查询需要花费太多的时间传输
下面的查询非常慢,我不明白为什么。我将所有id作为索引(一些主id) 在Wampserver的本地安装中,我在传输数据方面遇到了严重问题。在海蒂身上,我看到两个分别为2秒和6秒的“发送数据”。 在共享服务器上,这是我看到的重要部分:Mysql 复杂查询需要花费太多的时间传输,mysql,sql,Mysql,Sql,下面的查询非常慢,我不明白为什么。我将所有id作为索引(一些主id) 在Wampserver的本地安装中,我在传输数据方面遇到了严重问题。在海蒂身上,我看到两个分别为2秒和6秒的“发送数据”。 在共享服务器上,这是我看到的重要部分: | statistics | 0.079963 | | preparing | 0.000028 | | Creating tmp table | 0.0000
| statistics | 0.079963 |
| preparing | 0.000028 |
| Creating tmp table | 0.000037 |
| executing | 0.000005 |
| Copying to tmp table | 7.963576 |
| converting HEAP to MyISAM | 0.015790 |
| Copying to tmp table on disk | 5.383739 |
| Creating sort index | 0.015143 |
| Copying to group table | 0.023708 |
| converting HEAP to MyISAM | 0.014513 |
| Copying to group table | 0.099595 |
| Sorting result | 0.034256 |
考虑到我想改进查询(请参见限制)或删除rand()并添加权重,我有点担心我做了一些非常错误的事情
其他信息:
工具台有500.000行,而仪器大约有6000行。仪器和工具约为3M排。
查询是为了找到我可以用我拥有的仪器制作的工具(通过在(仪器id)中检查t.id)。Group_concat(t.name)是一种知道选择了哪种仪器的方法
解释问题:
+----+-------------+-------+--------+-------------------------+---------------+-------- -+----------------------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-------------------------+---------------+---------+----------------------------+------+----------------------------------------------+
| 1 | SIMPLE | t | range | PRIMARY | PRIMARY | 4 | NULL | 3 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | ifr | ref | id_tool,id_instrument | id_instrument | 5 | mydb2.t.id | 374 | Using where |
| 1 | SIMPLE | r | eq_ref | PRIMARY | PRIMARY | 4 | mydb2.ifr.id_tool | 1 | |
+----+-------------+-------+--------+-------------------------+---------------+---------+----------------------------+------+----------------------------------------------+
交叉点表上需要一个复合索引:
ALTER TABLE instruments_tools ADD KEY (id_instrument, id_tool);
该索引中列的顺序很重要
您希望的是,连接将从instrument表开始,然后在基于id_instrument的复合索引中查找匹配的索引项。然后,一旦找到该索引项,它将免费拥有相关的id_工具。因此它根本不必读取instrument_tools表,它只需要读取索引项。这应该在仪器工具表的说明中给出“使用索引”注释
这应该会有所帮助,但您不能避免使用临时表和文件排序,因为您分组和排序所依据的列不能使用索引
您可以通过增加可用于临时表的内存大小,使MySQL避免将临时表写入磁盘:
mysql> SET GLOBAL tmp_table_size = 256*1024*1024; -- 256MB
mysql> SET GLOBAL max_heap_table_size = 256*1024*1024; -- 256MB
这个数字只是一个例子。我不知道在您的情况下,temp表必须有多大。首先要做的事情-您所有的where列和join列都被索引了吗?此查询是否对您有更好的效果?选择r.name作为工具,r.url url,r.id\u工具recId,count(*)作为计数,r.source作为源,group_concat(t.name)作为工具r内部连接工具r内部连接工具ifr ON r.id_tool=ifr.id_tool=--JOIN是向后的,ifr.id_工具t ON ifr.id_instrument=t.id--JOIN向后和t.id IN(433,37,362)和t.source IN(1,2,3)组按r.id_工具顺序按计数描述,rand()另一个想法是,你可以考虑改写从工具ToeTooer->工具->工具(排序最大到最小)的查询。不确定这是否有助于MySQL的优化器。@ Brand,优化器将重新排序表,而不管查询中指定的顺序是什么。(除非您使用“直接连接”覆盖该行为)。@dgig是的,它们都被索引。id和源。谢谢。我会试试这个。有没有办法猜测临时表的大小?我想这取决于我选择了多少仪器(id在(…)中)是的,每个查询都会有所不同。我知道获得每个查询的临时表大小的真实记录的唯一方法是Percona服务器额外详细的慢速查询日志中的
Tmp_table_size
字段。从我的初始测试看,它似乎已经起作用了!我看到0.04s复制到组表,0.03复制到磁盘上的Tmp表!太好了!祝贺你。是的,复合输入索引对于某些类型的查询非常重要。我曾经做过的最好的例子是使用复合索引将客户的查询速度提高9400万倍。:-)
mysql> SET GLOBAL tmp_table_size = 256*1024*1024; -- 256MB
mysql> SET GLOBAL max_heap_table_size = 256*1024*1024; -- 256MB