下面的查询很慢,不明白为什么。我将所有 id 作为索引(一些主要的)。
SELECT r.name as tool, r.url url ,r.id_tool recId, count(*) as count, r.source as source,
group_concat(t.name) as instrument
FROM tools r
INNER JOIN
instruments_tools ifr
ON ifr.id_tool = r.id_tool
INNER JOIN
instrument t
ON t.id= ifr.id_instrument
WHERE t.id IN (433,37,362) AND t.source IN (1,2,3)
GROUP BY r.id_tool
ORDER BY count desc,rand() limit 10;
在 Wampserver 安装本地,我在传输数据时遇到严重问题。对于 Heidi,我看到两个“发送数据”,分别为 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 |
考虑到我想改进查询(参见 LIMIT)或删除 rand() 并添加权重,我有点担心我做错了。
附加信息: tools 表有 500.000 行大,而 instruments 表大约有 6000 行。instruments_tools 大约有 3M 行。 查询是找到我可以使用我拥有的仪器制作的工具(通过检查 t.id IN(仪器的 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_tool。所以它根本不用读取instrument_tools表,只需要读取索引条目即可。这应该在 instruments_tools 表的 EXPLAIN 中给出“使用索引”注释。
这应该有所帮助,但您无法避免使用临时表和文件排序,因为您分组和排序所依据的列无法使用索引。
您可以尝试通过增加可用于临时表的内存大小来使 MySQL 避免将临时表写入磁盘:
mysql> SET GLOBAL tmp_table_size = 256*1024*1024; -- 256MB
mysql> SET GLOBAL max_heap_table_size = 256*1024*1024; -- 256MB
这个数字只是一个例子。我不知道你的临时表需要多大。
关于mysql - 复杂的查询需要太多时间传输,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24069216/