MySQL:如何索引“OR"条款

MySQL: how to index an quot;ORquot; clause(MySQL:如何索引“OR条款)
本文介绍了MySQL:如何索引“OR"条款的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在执行以下查询

SELECT COUNT(*)
FROM table
WHERE field1='value' AND (field2 >= 1000 OR field3 >= 2000)

field1 上有一个索引,field2&field3 上有另一个组合.

There is one index over field1 and another composited over field2&field3.

我看到 MySQL 总是选择 field1 索引,然后使用其他两个字段进行连接,这很糟糕,因为它需要连接 146.000 行.

I see MySQL always selects the field1 index and then makes a join using the other two fields which is quite bad because it needs to join 146.000 rows.

关于如何改进的建议?谢谢

Suggestions on how to improve this? Thanks

(尝试提出的解决方案后进行编辑)

(EDIT AFTER TRYING SOLUTION PROPOSED)

基于提出的解决方案,我在玩这个时在 Mysql 上看到了这个.

Based in the solution proposed I've seen this on Mysql when playing with this.

SELECT COUNT(*) FROM (SELECT * FROM table WHERE columnA = value1
UNION SELECT * FROM table WHERE columnB = value2) AS unionTable;

比执行慢很多:

SELECT COUNT(*)
FROM table
WHERE (columnA = value1 AND columnB = value2)
      OR (columnA = value1 AND columnC = value3)

有两个复合索引:

index1 (columnA,columnB)
index2 (columnA,columnC)

有趣的是,要求 Mysql解释"它在这两种情况下总是采用 index1 的查询,并且不使用 index2.

Interesting enough is that asking Mysql to "explain" the query it's taking always index1 on both cases and index2 is not used.

如果我将索引更改为:

index1 (columnB,columnA)
index2 (columnC,columnA)

查询到:

SELECT COUNT(*)
FROM table
WHERE (columnB = value2 AND columnA = value1)
      OR (columnC = value3 AND columnA = value1)

这是我发现 Mysql 工作最快的方法.

Then it's the fastest way I've found Mysql works.

推荐答案

分解 OR 谓词的典型方法是使用 UNION.

The typical way to break up OR predicates is with UNION.

请注意,您的示例不适合您的索引.即使您从谓词中省略了 field1,您也会有 field2 >= 1000 OR field3 >= 2000,它不能使用索引.如果您分别在 (field1, field2)(field1,field3)field2field3 上有索引,你会得到一个相当快的查询.

Note that your example doesn't fit well with your indexes. Even if you omitted field1 from the predicate, you'd have field2 >= 1000 OR field3 >= 2000, which can't use an index. If you had indexes on (field1, field2) and (field1,field3) or field2 or field3 separately, you would get a reasonably fast query.

SELECT COUNT(*) FROM
(SELECT * FROM table WHERE field1 = 'value' AND field2 >= 1000
UNION
SELECT * FROM table WHERE field1 = 'value' AND field3 >= 2000) T

请注意,您必须为派生表提供别名,这就是子查询别名为T的原因.

Note that you have to provide an alias for the derived table, which is why the subquery is aliased as T.

一个真实的例子.列名和表名已匿名!

A real-world example. Column and table names have been anonymized!

mysql> SELECT COUNT(*) FROM table;
+----------+
| COUNT(*) |
+----------+
|  3059139 |
+----------+
1 row in set (0.00 sec)

mysql> SELECT COUNT(*) FROM table WHERE columnA = value1;
+----------+
| COUNT(*) |
+----------+
|     1068 |
+----------+
1 row in set (0.00 sec)

mysql> SELECT COUNT(*) FROM table WHERE columnB = value2;
+----------+
| COUNT(*) |
+----------+
|      947 |
+----------+
1 row in set (0.00 sec)

mysql> SELECT COUNT(*) FROM table WHERE columnA = value1 OR columnB = value2;
+----------+
| COUNT(*) |
+----------+
|     1616 |
+----------+
1 row in set (9.92 sec)

mysql> SELECT COUNT(*) FROM (SELECT * FROM table WHERE columnA = value1
UNION SELECT * FROM table WHERE columnB = value2) T;
+----------+
| COUNT(*) |
+----------+
|     1616 |
+----------+
1 row in set (0.17 sec)

mysql> SELECT COUNT(*) FROM (SELECT * FROM table WHERE columnA = value1
UNION ALL SELECT * FROM table WHERE columnB = value2) T;
+----------+
| COUNT(*) |
+----------+
|     2015 |
+----------+
1 row in set (0.12 sec)

这篇关于MySQL:如何索引“OR"条款的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Hibernate reactive No Vert.x context active in aws rds(AWS RDS中的休眠反应性非Vert.x上下文处于活动状态)
Bulk insert with mysql2 and NodeJs throws 500(使用mysql2和NodeJS的大容量插入抛出500)
Flask + PyMySQL giving error no attribute #39;settimeout#39;(FlASK+PyMySQL给出错误,没有属性#39;setTimeout#39;)
auto_increment column for a group of rows?(一组行的AUTO_INCREMENT列?)
Sort by ID DESC(按ID代码排序)
SQL/MySQL: split a quantity value into multiple rows by date(SQL/MySQL:按日期将数量值拆分为多行)