Mysql 使用filesort&;简单地选择组;临时的,不是索引的
所以我浏览了一下网络,似乎找不到答案。我有一张结构如下的桌子Mysql 使用filesort&;简单地选择组;临时的,不是索引的,mysql,sql,Mysql,Sql,所以我浏览了一下网络,似乎找不到答案。我有一张结构如下的桌子 Table structure for table `search_tags` -- CREATE TABLE IF NOT EXISTS `search_tags` ( `ID` int(11) NOT NULL AUTO_INCREMENT, `LOOK_UP_TO_CAT_ID` int(11) NOT NULL, `SEARCH_TAG` text COLLATE utf8_unicode_520_ci NOT
Table structure for table `search_tags`
--
CREATE TABLE IF NOT EXISTS `search_tags` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`LOOK_UP_TO_CAT_ID` int(11) NOT NULL,
`SEARCH_TAG` text COLLATE utf8_unicode_520_ci NOT NULL,
`DATE` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`SOURCE` varchar(225) COLLATE utf8_unicode_520_ci NOT NULL,
`SOURCE_ID` int(11) NOT NULL,
`WEIGHT` int(11) NOT NULL DEFAULT '1000',
PRIMARY KEY (`ID`),
KEY `LOOK_UP_TO_CAT_ID` (`LOOK_UP_TO_CAT_ID`),
KEY `WEIGHT` (`WEIGHT`),
FULLTEXT KEY `SEARCH_TAG` (`SEARCH_TAG`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_520_ci AUTO_INCREMENT=1 ;
该表包含800000多行,并且正在增长
当我在LOOK\u UP\u TO \u CAT\u ID
上使用group by运行查询时,运行查询需要1-2秒。我需要运行此基础的多个版本,并将其连接到其他表,但这似乎是瓶颈所在,因为向其中添加连接并不会降低速度
SELECT LOOK_UP_TO_CAT_ID, WEIGHT
FROM `search_tags`
WHERE `SEARCH_TAG` LIKE '%metallica%'
GROUP BY `LOOK_UP_TO_CAT_ID`
删除groupby
会将查询时间降低到0.1,这似乎更容易接受,但随后我就得到了重复的查询时间
对groupby使用explain表明它正在创建一个临时表,而不是使用索引
+----+-------------+-------------+------+-------------------+------+---------+------+--------+----------------------------------------------+--+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | |
+----+-------------+-------------+------+-------------------+------+---------+------+--------+----------------------------------------------+--+
| 1 | SIMPLE | search_tags | ALL | LOOK_UP_TO_CAT_ID | NULL | NULL | NULL | 825087 | Using where; Using temporary; Using filesort | |
+----+-------------+-------------+------+-------------------+------+---------+------+--------+----------------------------------------------+--+
所以我不确定mysql是否在这里做了正确的事情,但至少对我来说,不使用索引似乎是错误的。为什么要加快查询速度,最好的方法是什么
编辑:
以下是我的数据示例:
+----+-------------------+----------------------------------+------------+---------------+-----------+--------+
| ID | LOOK_UP_TO_CAT_ID | SEARCH_TAG | DATE | SOURCE | SOURCE_ID | WEIGHT |
+----+-------------------+----------------------------------+------------+---------------+-----------+--------+
| 1 | 521 | METALLICA | 2017-02-18 | artist | 15 | 1 |
| 2 | 521 | METALLICA - NOTHING ELSE MATTERS | 2017-02-18 | tracklisting | 22 | 2 |
| 3 | 522 | METALLICA | 2017-02-18 | artist | 15 | 1 |
| 4 | 522 | METALLICA - ST. Anger | 2017-02-18 | product_title | 522 | 2 |
+----+-------------------+----------------------------------+------------+---------------+-----------+--------+
期望结果
+-------------------+--------+
| LOOK_UP_TO_CAT_ID | WEIGHT |
+-------------------+--------+
| 521 | 1 |
| 522 | 1 |
+-------------------+--------+
在某种程度上,你的问题没有意义。您有一个全文索引,但使用的是像一样的
,它执行表格扫描。您需要使用MATCH()
来使用全文索引
我真正认为正在发生的是返回的数据量很大。如果执行查询时没有按
排序或按分组,则会在生成结果时返回结果。您可以看到结果,因为早期扫描的某些行符合您的条件
分组依据
/排序依据
需要读取所有结果
您可以通过执行计数(*)
而不是选择来检查这一点:
SELECT COUNT(*)
FROM `search_tags`
WHERE `SEARCH_TAG` LIKE '%metallica%';
我怀疑这可能需要更长的时间
通过使用相关子查询,可以消除重复消除的性能影响:
SELECT st.LOOK_UP_TO_CAT_ID, st.WEIGHT
FROM `search_tags` st
WHERE `SEARCH_TAG` LIKE '%metallica%' AND
st.id = (SELECT MIN(st2.id) FROM search_tags st2 WHERE st2.LOOK_UP_TO_CAT_ID = st.LOOK_UP_TO_CAT_ID);
这特别需要在search\u标签(查找到\u CAT\u ID,ID)
上建立索引以提高性能
但是,您可能还想使用MATCH()
来利用全文索引。给您一些建议
SEARCH\u像“%metallica%”这样的标签
在这个不幸的世界里永远不会使用索引。类似于“%needle”
(前导%
)的模式需要MySQL检查列中的每个值是否匹配<代码>干草堆,如“针%”
(尾随%
)不存在此问题
SEARCH\u标签上有列,所以请使用它WHERE-MATCH('metallica')与SEARCH_标记
是您需要的WHERE子句的形式
SELECT LOOK_UP_TO_CAT_ID, WEIGHT
FROM search_tags
WHERE SEARCH_TAG LIKE '%metallica%'
GROUP BY LOOK_UP_TO_CAT_ID
如果您将其更改为此,它将更有SQL意义,并且运行得更快
SELECT LOOK_UP_TO_CAT_ID, MAX(WEIGHT)
FROM search_tags
WHERE SEARCH_TAG LIKE 'metallica%'
GROUP BY LOOK_UP_TO_CAT_ID
(注意,我去掉了前面的%
)
如果在上添加复合覆盖索引(搜索标记,查找类别ID,权重)
此查询将变得非常快速。通过索引可以满足整个查询。MySQL随机访问索引以查找您的搜索标记,然后执行搜索以获得您请求的结果
(旁白:当您在
EXPLAIN
中看到filesort
在groupby
或orderby
查询中的输出时,不要担心。这是MySQL满足查询的一部分。filesort
中的文件不一定意味着硬盘上的文件速度慢。)使用SELECT*
和groupby
仅仅表明对SQL的理解很差。编辑您的问题并提供示例数据和所需结果。感谢您的解释。我采用了对抗法,因为这在我的情况下非常有效(从性能上看)。