非常慢的查询曾经非常快。解释显示本地备份上的 rows=1,但服务器上的 rows=2287359

发布于 2024-10-08 20:38:37 字数 1039 浏览 0 评论 0原文

我时不时地检查垃圾邮件,然后使用“从像 '%http://%' order by id desc limit 10 的帖子中选择 *”并搜索其他一些关键字。最近,选择速度慢得令人难以置信。

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)

在我的上网本上,有 1 GB 内存,唯一的区别是它显示“ROWS”列为 1。我的上网本中只有 130 万个帖子。该服务器有大约 6 GB 内存和一个快速处理器。我应该优化什么,这样它才不会太慢。最近,我添加了一个索引来按 userId 进行搜索,我不确定这是否是一个明智的选择,但在这个问题开始发生之前,我将其添加到了备份和生产服务器中。我想这与由于错过调整而无法在内存中排序有关?

当我做“从 threadId=X 的帖子中删除”之类的事情时,它似乎也很慢,不知道是否相关。

I check for spam every now and then using "select * from posts where post like '%http://%' order by id desc limit 10" and searching a few other keywords. Lately the select is impossibly slow.

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)

On my netbook with 1 gig ram the only difference is it shows the "ROWS" column as being 1. There is only 1.3 mil posts in my netbook. The server has like 6 gigs ram and a fast processor. What should I optimize so it's not horribly slow. Recently I added an index to search by userId, which I'm not sure was a smart choice, but I added it to the backup and production server both a little before this issue started happening. I'd imagine it's related to it not being able to sort in ram due to a missed tweak?

It also seems to be slow when I do stuff like "delete from posts where threadId=X", dunno if related.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

错爱 2024-10-15 20:38:37

关于

SELECT * FROM posts WHERE reply LIKE "%http://%" ORDER BY id DESC LIMIT 1

由于 http://,MySQL 将无法使用 reply 上的索引来快速找到您要查找的内容。此外,由于您要求的是具有最大id的结果,MySQL将必须提取所有结果以确保您拥有具有最大“id”的结果。

根据 posts 表中有多少数据由 reply 组成,可能值得在 (id,reply)< 上添加复合索引/code>,并将查询更改为类似

SELECT id FROM posts WHEREreply LIKE "%http://%" ORDER BY id DESC LIMIT 1

(这将仅执行索引),然后加入 posts 表或使用检索到的 id 检索帖子。如果查询仅执行索引,并且索引适合内存并且已经在内存中(由于正常使用或有意预热),您可能会加速启动查询执行。

话虽如此,如果具有相同数据的两个相同服务器上的相同查询给出了不同的执行计划和执行时间,那么可能是时候OPTIMIZE TABLE posts刷新索引统计信息和/或对表进行碎片整理了。如果您最近添加/删除了索引,事情可能会误入歧途。此外,如果数据是碎片化的,当它按主键顺序提取行时,它可能会跳过整个磁盘来检索数据。

对于DELETE FROM posts WHERE threadId=X,只要threadId上有索引就应该没问题。

With respect to

SELECT * FROM posts WHERE reply LIKE "%http://%" ORDER BY id DESC LIMIT 1

Due to the wild cards on both sides of the http://, MySQL will can not use an index on reply to quickly find what you're looking for. Moreover, since you're asking for the one with the largest id, MySQL will have to pull all results to make sure that you have the one with the largest `id'.

Depending how much of the data of the posts table is made up of the reply, it might be worthwhile to add a compound index on (id, reply), and change the query to something like

SELECT id FROM posts WHERE reply LIKE "%http://%" ORDER BY id DESC LIMIT 1

(which will have an index only execution), then join to the posts table or retrive the posts using the retrived ids. If the query has index only execution, and the index fits in memory and is already in memory (due to normal use or by intentionality warming it up), you could potentially speed up the query execution.

Having said all that, if identical queries on two identical servers with identical data are giving different execution plans and execution times, it might be time to OPTIMIZE TABLE posts to refresh the index statistics and/or defragment the table. If you have recently been adding/removing indexes, things might have gotten astray. Moreover, if the the data is fragmented, when it's pulling rows in PRIMARY KEY order, it could be jumping all over the disk to retrieve the data.

With respect to DELETE FROM posts WHERE threadId=X, it should be fine as long as there is an index on threadId.

摘星┃星的人 2024-10-15 20:38:37

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

where reply like "%http://%"

正如您的解释所证实的那样,没有使用任何索引。速度差异可能是由于缓存造成的。

Indexes won't be used if you start your search comparison with a "%". You problem is with

where reply like "%http://%"

As confirmed by your explain, no indexes are used. The speed difference may be due to caching.

痴者 2024-10-15 20:38:37

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

您的第一个查询(从帖子中选择*,其中像“%http://%”这样的帖子会因为查询中的“like”而变慢。我建议使用另一个 WHERE 子句过滤您的查询 - 也许按日期(即希望被索引):

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

What kind of indexes do you have on your table(s)? A good rule of thumb is to have an index on the columns that appear most often in your WHERE clause. If you do not have an index on your threadId column, your last query will be a lot slower than if you did.

Your first query (select * from posts where post like '%http://%' will be slow simply due to the "like" in the query. I would suggest filtering your query with another WHERE clause - perhaps by date (which is hopefully indexed):

select * from posts where postdate > 'SOMEDATE' and post like '%http://%'
木緿 2024-10-15 20:38:37

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

Can you write an after-insert trigger that examines the text looking for substring 'http://' and either flags the current record or writes out its id to a SPAM table? As @brent said, indexes are not used for "contains substring" searches.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文