Mysql:优化使用一列或另一列的查询
Posted
技术标签:
【中文标题】Mysql:优化使用一列或另一列的查询【英文标题】:Mysql: optimizing a query that uses one column or the other 【发布时间】:2021-03-14 07:26:32 【问题描述】:该表包含聊天数据,其中 from_user_id
和 to_user_id
列均已单独正确编入索引。我的查询是获取特定用户参与的所有聊天消息,即
SELECT * FROM chat WHERE from_user_id = 123 OR to_user_id = 123;
分别运行这两个条件时,它们使用各自的索引,但是当它们与 OR 拼接在一起时,解释查询使用的估计行数要高得多。你会如何优化它?
See screenshot of all these queries
【问题讨论】:
我们需要更多信息来帮助您。 Please read this 然后edit 你的问题。而且,请注意SELECT *
是大表上臭名昭著的性能反模式。
【参考方案1】:
把OR
变成UNION
:
SELECT * FROM chat WHERE from_user_id = 123 OR to_user_id = 123;
-->
( SELECT * FROM chat WHERE from_user_id = 123 )
UNION ALL
( SELECT * FROM chat WHERE to_user_id = 123 )
ORDER BY date;
还有
INDEX(from_user_id),
INDEX(to_user_id)
以便 每个 SELECT
得到很好的优化。
如果您要分页,请参阅如何使 OFFSET
工作:http://mysql.rjweb.org/doc.php/index_cookbook_mysql#or
如果你有其他口味的SELECT
,让我们看看。不同的查询需要不同的技术。例如,如果你有时需要AND
:
SELECT ... WHERE from_user_id = 123
AND to_user_id = 7777
需要其中一个:
INDEX(from_user_id, to_user_id)
INDEX(to_user_id, from_user_id)
如果您需要 OR 和 AND 查询,那么我会推荐 both 这些复合索引,而不是 我上面推荐的单列索引。 p>
(上面的链接在博客讨论索引的中间;全部阅读。)
【讨论】:
@TimBiegeleisen - 谢谢。呵呵——没有T恤。我有 50 多件来自公司和会议的 T 恤。 你应该得到一些东西......最终。见这里:Swag is coming back! 袜子!?这是一个有趣的赃物。【参考方案2】:MySQL 中的多列索引允许您从左到右使用索引中的所有字段。例如,如果您有一个 INDEX (col1, col2, col3, col4),那么该索引将应用于带有 WHERE 子句(如 col1 = 'A'
或 col1 = 'A' AND col2 = 'B'
或 col1 = 'A' AND col2 ='B' AND col3 = 'C' AND col4 = 'D'
)的搜索,但不会使用此特定索引对于WHERE col2 = 'B'
或WHERE col3 = 'C' AND col4 = 'D'
之类的任何内容,因为搜索字段不在索引定义中最左侧。您必须添加额外的索引来覆盖这些字段。
所以,如果你创建一个多列索引:
CREATE INDEX idx ON chat (from_user_id, to_user_id);
每当您执行如下选择时,
select * from chat where from_user_id = 123;
select * from chat where from_user_id = 123 or to_user_id=123;
在上述两种情况下,mysql都会应用索引。
对于下面的查询索引将不会被应用,
select * from chat where to_user_id=123;
select * from chat where to_user_id=123 or from_user_id = 123;
所以,根据你的需要规划你的索引。
【讨论】:
以上是关于Mysql:优化使用一列或另一列的查询的主要内容,如果未能解决你的问题,请参考以下文章