Mysql:优化使用一列或另一列的查询

Posted

技术标签:

【中文标题】Mysql:优化使用一列或另一列的查询【英文标题】:Mysql: optimizing a query that uses one column or the other 【发布时间】:2021-03-14 07:26:32 【问题描述】:

该表包含聊天数据,其中 from_user_idto_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:优化使用一列或另一列的查询的主要内容,如果未能解决你的问题,请参考以下文章

合并其中一列或另一列中缺少数据的数据框

如何根据另一列的值创建空列或非空列?

根据另一列的另一个值和/或另一行中的同一列更新设置值:-ORA 1427

根据MySQL中另一列分组的另一列的顺序更新列

如何根据另一列的单元格值由其他列动态更新A列

MariaDB/mysql SQL查询问题:我想根据另一列的组值对一列进行部分总和