我正在执行以下查询
SELECT COUNT(*)
FROM table
WHERE field1='value' AND (field2 >= 1000 OR field3 >= 2000)
在field1上有一个索引,在field2&field3上有另一个索引。
我看到MySQL总是选择field1索引,然后使用其他两个字段进行联接,这很糟糕,因为它需要联接146.000行。
关于如何改善这一点的建议?谢谢
(在尝试解决方案后进行编辑)
基于提出的解决方案,我在使用此工具时已经在Mysql上看到了。
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。
如果我将索引更改为:
index1 (columnB,columnA)
index2 (columnC,columnA)
和查询到:
SELECT COUNT(*)
FROM table
WHERE (columnB = value2 AND columnA = value1)
OR (columnC = value3 AND columnA = value1)
然后这是我发现Mysql工作最快的方式。
分解OR
谓词的典型方法是使用UNION
。
请注意,您的示例不太适合您的索引。即使您field1
从谓词中省略了,您也将拥有field2 >= 1000 OR field3 >= 2000
,它不能使用索引。如果您在(field1, field2)
和(field1,field3)
或(field2
或)上field3
分别有索引,您将获得一个相当快速的查询。
SELECT COUNT(*) FROM
(SELECT * FROM table WHERE field1 = 'value' AND field2 >= 1000
UNION
SELECT * FROM table WHERE field1 = 'value' AND field3 >= 2000) T
请注意,您必须为派生表提供别名,这就是为什么子查询被别名为的原因T
。
一个真实的例子。列名和表名已匿名!
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索引的工作方式非常感兴趣,更具体地说,它们如何在不扫描整个表的情况下返回请求的数据? 我知道这是题外话,但是如果有人可以向我详细解释一下,我将非常非常感谢。 问题答案: 基本上,表上的索引的作用类似于书中的索引(这就是名称的来源): 假设您有一本关于数据库的书,并且想要查找有关存储的信息。没有索引(假设没有其他帮助,例如目录),则必须逐个浏览页面,直到找到主题(即)为止。
本文向大家介绍MySQL如何优化索引,包括了MySQL如何优化索引的使用技巧和注意事项,需要的朋友参考一下 1. MySQL如何使用索引 索引用于快速查找具有特定列值的行。如果没有索引,MySQL必须从第一行开始,然后遍历整个表以找到相关的行。表越大,花费越多。如果表中有相关列的索引,MySQL可以快速确定要在数据文件中间查找的位置,而不必查看所有数据。这比顺序读取每一行要快得多。 大多数MyS
问题内容: 我正在尝试获取id = 3或id = 9或id = 100的内容…请记住,我可以拥有几百个这些ID。 编写查询的最有效方法是什么? 问题答案:
主要内容:为什么要使用索引,索引的优缺点索引是一种特殊的数据库结构,由数据表中的一列或多列组合而成,可以用来快速查询数据表中有某一特定值的记录。本节将详细讲解索引的含义、作用和优缺点。 通过索引,查询数据时不用读完记录的所有信息,而只是查询索引列。否则,数据库系统将读取每条记录的所有信息进行匹配。 可以把索引比作新华字典的音序表。例如,要查“库”字,如果不使用音序,就需要从字典的 400 页中逐页来找。但是,如果提取拼音出来,构成音序表
本文向大家介绍MySQL索引之主键索引,包括了MySQL索引之主键索引的使用技巧和注意事项,需要的朋友参考一下 在MySQL里,主键索引和辅助索引分别是什么意思,有什么区别? 上次的分享我们介绍了聚集索引和非聚集索引的区别,本次我们继续介绍主键索引和辅助索引的区别。 1、主键索引 主键索引,简称主键,原文是PRIMARY KEY,由一个或多个列组成,用于唯一性标识数据表中的某一条记录。一个表可以没
问题内容: 我想重命名索引。我看过alter table文档,但无法弄清楚简单地重命名索引的语法。通过MySQL GUI进行操作时,它将删除索引并创建一个新索引。在这种情况下,我希望避免仅为了更改索引名称而重建整个索引。 [附加信息] 在alter table文档中指出 可以通过更改表的.frm文件而不接触表内容来立即进行仅修改表元数据而不修改表数据的更改。以下更改是可以通过这种方式进行的快速更改