Mysql 复杂查询需要花费太多的时间传输

Mysql 复杂查询需要花费太多的时间传输,mysql,sql,Mysql,Sql,下面的查询非常慢,我不明白为什么。我将所有id作为索引(一些主id) 在Wampserver的本地安装中,我在传输数据方面遇到了严重问题。在海蒂身上,我看到两个分别为2秒和6秒的“发送数据”。 在共享服务器上,这是我看到的重要部分: | statistics | 0.079963 | | preparing | 0.000028 | | Creating tmp table | 0.0000

下面的查询非常慢,我不明白为什么。我将所有id作为索引(一些主id)

在Wampserver的本地安装中,我在传输数据方面遇到了严重问题。在海蒂身上,我看到两个分别为2秒和6秒的“发送数据”。 在共享服务器上,这是我看到的重要部分:

| 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