Mysql 非常慢的查询过去非常快。解释显示本地备份上的行数为1,但服务器上的行数为2287359

Mysql 非常慢的查询过去非常快。解释显示本地备份上的行数为1,但服务器上的行数为2287359,mysql,sql,sql-order-by,sql-like,sql-execution-plan,Mysql,Sql,Sql Order By,Sql Like,Sql Execution Plan,我时不时地使用select*from post检查垃圾邮件,如“%http://%”order by id desc limit 10,并搜索一些其他关键字。最近,select速度慢得令人难以置信 mysql> explain select * from posts where reply like "%http://%" order by id desc limit 1; +----+-------------+-----------+-------+---------------+--

我时不时地使用select*from post检查垃圾邮件,如“%http://%”order by id desc limit 10,并搜索一些其他关键字。最近,select速度慢得令人难以置信

mysql> explain select * from posts where reply like "%http://%" order by id desc limit 1;
+----+-------------+-----------+-------+---------------+---------+---------+------+---------+-------------+
| id | select_type | table     | type  | possible_keys | key     | key_len | ref  | rows    | Extra       |
+----+-------------+-----------+-------+---------------+---------+---------+------+---------+-------------+
|  1 | SIMPLE      | posts     | index | NULL          | PRIMARY | 4       | NULL | 2287347 | Using where |
+----+-------------+-----------+-------+---------------+---------+---------+------+---------+-------------+
1 row in set (0.00 sec)
在我的1GRAM上网本上,唯一的区别是它显示的行列为1。我的上网本里只有130万条帖子。该服务器有6千兆内存和一个快速处理器。我应该优化什么,使它不会太慢。最近,我添加了一个按用户ID搜索的索引,我不确定这是一个明智的选择,但在这个问题开始出现之前,我将它添加到了备份和生产服务器。我想这与它由于错过了一个调整而无法在ram中排序有关


当我从threadId=X的帖子中删除内容时,速度似乎也很慢,如果相关的话不知道。

您的表上有什么类型的索引?一个好的经验法则是在WHERE子句中最常出现的列上有一个索引。如果您的threadId列上没有索引,那么您的上一次查询将比您的查询慢得多

您的第一个查询从post中选择*,其中类似于“%http://%”的post将由于查询中的like而变慢。我建议您使用另一个WHERE子句过滤您的查询-可能是按日期,希望索引:

select * from posts where postdate > 'SOMEDATE' and post like '%http://%'

您的表上有什么类型的索引?一个好的经验法则是在WHERE子句中最常出现的列上有一个索引。如果您的threadId列上没有索引,那么您的上一次查询将比您的查询慢得多

您的第一个查询从post中选择*,其中类似于“%http://%”的post将由于查询中的like而变慢。我建议您使用另一个WHERE子句过滤您的查询-可能是按日期,希望索引:

select * from posts where postdate > 'SOMEDATE' and post like '%http://%'

如果以%开始搜索比较,则不会使用索引。你的问题在于

where reply like "%http://%"

正如您的解释所确认的,没有使用索引。速度差异可能是由于缓存造成的。

如果以%开始搜索比较,则不会使用索引。你的问题在于

where reply like "%http://%"

正如您的解释所确认的,没有使用索引。速度差异可能是由于缓存造成的。

是否可以编写一个后插入触发器,用于检查文本以查找子字符串“http://”,并标记当前记录或将其id写入垃圾邮件表?正如@brent所说,索引不用于包含子字符串的搜索。

您是否可以编写一个后插入触发器来检查查找子字符串“http://”的文本,并标记当前记录或将其id写入垃圾邮件表?正如@brent所说,索引不用于包含子字符串搜索。

关于

从回复为%http://%ORDER BY id DESC LIMIT 1的帖子中选择*

由于http:///的两边都有通配符,MySQL无法在回复时使用索引来快速查找您要查找的内容。此外,由于您要求的是id最大的一个,MySQL将不得不提取所有结果,以确保您拥有id最大的一个

根据posts表中有多少数据是由reply组成的,可能需要在id、reply上添加一个复合索引,并将查询更改为

从回复为%http://%ORDER BY id DESC LIMIT 1的帖子中选择id

它将只执行索引,然后连接到posts表或使用检索的id检索posts。如果查询只有索引执行,并且索引适合内存,并且由于正常使用或有意对其进行预热而已在内存中,则可能会加快查询执行

综上所述,如果两台相同服务器上具有相同数据的相同查询给出不同的执行计划和执行时间,那么可能是时候优化表POST以刷新索引统计信息和/或对表进行碎片整理了。如果您最近一直在添加/删除索引,则可能会误入歧途。此外,如果数据是碎片化的,当它按主键顺序拉动行时,它可能会在整个磁盘上跳跃以检索数据

关于从threadId=X的帖子中删除,只要threadId上有索引就可以了

关于

从回复为%http://%ORDER BY id DESC LIMIT 1的帖子中选择*

由于http:///的两边都有通配符,MySQL无法在回复时使用索引来快速查找您要查找的内容。此外,由于您要求的是id最大的一个,MySQL将不得不提取所有结果,以确保您拥有id最大的一个

根据posts表中有多少数据是由reply组成的,可能需要在id、reply上添加一个复合索引,并将查询更改为

从帖子中选择id 其中回复类似于%http://%ORDER BY id DESC LIMIT 1

它将只执行索引,然后连接到posts表或使用检索的id检索posts。如果查询只有索引执行,并且索引适合内存,并且由于正常使用或有意对其进行预热而已在内存中,则可能会加快查询执行

综上所述,如果两台相同服务器上具有相同数据的相同查询给出不同的执行计划和执行时间,那么可能是时候优化表POST以刷新索引统计信息和/或对表进行碎片整理了。如果您最近一直在添加/删除索引,则可能会误入歧途。此外,如果数据是碎片化的,当它按主键顺序拉动行时,它可能会在整个磁盘上跳跃以检索数据


关于从threadId=X的帖子中删除,只要threadId上有索引就可以了

为什么像这样的“anywhere”不好:我的意思是,在解释查询中,行显示为2287347,而在解释备份时,行显示为=1。在这两种情况下,我都使用limit 1,但出于某种原因,在服务器上它正在加载所有内容或搜索所有内容。查询过去很快。我认为order by ID desc速度更快,因为通常它不必在我认为是主键时进行排序,我不确定!。你能试试力指数吗;为什么像这样的“anywhere”不好:我的意思是,在解释查询中,行显示为2287347,而在解释备份时,行显示为=1。在这两种情况下,我都使用limit 1,但出于某种原因,在服务器上它正在加载所有内容或搜索所有内容。查询过去很快。我认为order by ID desc速度更快,因为通常它不必在我认为是主键时进行排序,我不确定!。你能试试力指数吗;是否可以显示包含索引的表的CREATE语句?是否可以显示包含索引的表的CREATE语句?