我有以下查询,这总是使整个网站失败,因为等待表级锁定":
/*IPS\Patterns\_ActiveRecordIterator::count:246*/ SELECT SQL_CALC_FOUND_ROWS forums_posts . * , forums_topics . *
FROM `forums_posts`
LEFT JOIN `forums_topics` ON forums_posts.topic_id = forums_topics.tid
LEFT JOIN `core_permission_index` ON core_permission_index.app = 'forums'
AND core_permission_index.perm_type = 'forum'
AND core_permission_index.perm_type_id = forums_topics.forum_id
LEFT JOIN `forums_forums` ON forums_topics.forum_id = forums_forums.id
WHERE (
NULLIF( forums_topics.moved_to, '' ) IS NULL
)
AND (
forums_forums.password IS NULL
OR (
(
FIND_IN_SET( 2, forums_forums.password_override )
)
)
)
AND (
forums_forums.can_view_others =1
OR forums_topics.starter_id IS NULL
)
AND forums_forums.min_posts_view <=0
AND queued =0
AND forums_topics.approved =1
AND (
(
(
FIND_IN_SET( 2, perm_2 )
)
)
OR perm_2 = '*'
)
ORDER BY post_date DESC
LIMIT 185725 , 25
我有什么办法可以改善这个查询的性能而不是杀死进程/等待10分钟直到它完成?
答案 0 :(得分:0)
如果这是一个“爬虫”,它正在给你的网站带来麻烦,你真的必须摆脱OFFSET
的使用。或者获取一些过滤器以防止实际上是DOS(拒绝服务)攻击。至少告诉搜索机器人避开你的网站。 (这可能是一个简单的答案。)
让我们变得真实。 LIMIT 185725 , 25
- 那是第7429页。你真的穿过了那么多页吗?
你有什么行有这么多行,却没有方便的方法来“搜索”或“合并”数据?
其他问题:
OR
代价高昂 - 它会阻止索引使用
LEFT JOIN
经常需要查看“正确”的表格,但在没有任何内容时感到高兴。这可能比普通JOIN
的性能更差。 (但是,业务逻辑可能需要它。)
由于查询的复杂性,SQL_CALC_FOUND_ROWS
可能几乎与获取LIMIT
的所有行一样长。注意搜索引擎过去常常说“大约180,000”的结果,然后就放弃了。也许你的应用也应该这样做。
肯定有一种更简单的方法NULLIF( forums_topics.moved_to, '' ) IS NULL
。
你在桌子上使用什么引擎?如果使用MyISAM,请切换到InnoDB;这可能会摆脱“桌面锁定”。
答案 1 :(得分:0)
请检查表类型是否为InnoDB。如果是MyISAM,请将其转换为InnoDB。当一些其他线程/查询正在更新该表中的任何行时,MyISAM无法读取表中的数据。它使用表级锁。
InnoDB使用MVCC在UPDATEs / INSERTs / DELETE更新表时启用SELECT。