Mysql 使用WHERE和GROUP BY进行查询时使用的最有效索引?
我有一个约700万行的表,我一直在运行这类查询:Mysql 使用WHERE和GROUP BY进行查询时使用的最有效索引?,mysql,sql,optimization,indexing,query-optimization,Mysql,Sql,Optimization,Indexing,Query Optimization,我有一个约700万行的表,我一直在运行这类查询: SELECT MyField, COUNT(*) FROM MyTable WHERE MyField2='ConstantValue' AND MyField NOT IN ( SELECT Field FROM AnotherTable) AND Timestamp >
SELECT
MyField,
COUNT(*)
FROM
MyTable
WHERE
MyField2='ConstantValue'
AND MyField NOT IN ( SELECT Field
FROM AnotherTable)
AND Timestamp >= [ArbitraryTimestamp]
GROUP BY
MyField;
上述字段的基数:
- MyField=大约40000个不同的值
- Timestamp=大多数是不同的,因此大约有700万个不同的值
- MyField2=2个不同的值
- 另一个表中的字段=大约50个不同的值
EXPLAIN
告诉我我正在使用where;使用临时设备;使用文件排序
我想通过向该表添加索引来提高这些查询的效率,但我不确定最好的方法是什么
我应该在MyField
上添加索引吗?并在时间戳上索引
?二者都两者的综合指数
另外,我还可以做些什么来加速这些类型的查询吗?您应该首先使用MyField添加一个双键索引(以分组方式):
您应该首先使用MyField添加一个双键索引(分组依据):
MyField上的
GROUPBY
将迫使MySQL创建一个临时表,这就是为什么在解释中使用临时的。创建一个有700万行的临时表肯定是一个痛苦的查询
尝试几件事(在实现每个建议后,重新运行查询并检查查询时间):
将索引添加到MyField
查看是否可以通过添加最大时间戳(结合最小时间戳)来限制行数
仅向MyField2和MyField3列添加索引
如果查询响应仍然很慢,请尝试在所有三列(Myfield、MyField2和MyField3)中添加复合索引
如果上面的任何一项都不能立即帮助您,请查看下面这篇文章,它描述了如何使用子查询来获取计数,从而完全避免了分组方式。MyField上的GROUPBY
将强制MySQL创建临时表,这就是为什么您在解释中使用了临时。创建一个有700万行的临时表肯定是一个痛苦的查询
尝试几件事(在实现每个建议后,重新运行查询并检查查询时间):
将索引添加到MyField
查看是否可以通过添加最大时间戳(结合最小时间戳)来限制行数
仅向MyField2和MyField3列添加索引
如果查询响应仍然很慢,请尝试在所有三列(Myfield、MyField2和MyField3)中添加复合索引
如果上述任何一项都不能立即帮助您,请查看下面这篇文章,它描述了如何使用子查询来获取计数,从而完全避免分组。除了Mike和DKamins的建议之外,拥有子查询可能是另一个瓶颈。我会将其重新构造为左联接,其中apply-based为NULL(确保“AnotherTable”在联接的“field”上有一个索引)
SELECT
MyField,
COUNT(*)
FROM
MyTable
LEFT join AnotherTable
on MyTable.MyField = AnotherTable.Field
WHERE
MyField2='ConstantValue'
AND AnotherTable.Field IS NULL
AND Timestamp >= [ArbitraryTimestamp]
GROUP BY
MyField;
我会特别根据(MyField2,TimeStamp,MyField)创建索引.MyField2是您的特定限定符,不要麻烦在您的焦点中包含其他crud…从这一点来看,您正在查看特定的时间框架…从这一点来看,拥有MyField也将有助于优化GroupBy。键的前两部分/其中,它专门用于筛选您的条件,因此其余部分已按正确顺序保留r分组。除了Mike和DKamins的建议外,拥有子查询可能是另一个瓶颈。我会将其重新构造为左联接,并且基于的应用为空(确保“AnotherTable”在联接的“field”上有一个索引
SELECT
MyField,
COUNT(*)
FROM
MyTable
LEFT join AnotherTable
on MyTable.MyField = AnotherTable.Field
WHERE
MyField2='ConstantValue'
AND AnotherTable.Field IS NULL
AND Timestamp >= [ArbitraryTimestamp]
GROUP BY
MyField;
我会特别根据(MyField2,TimeStamp,MyField)创建索引.MyField2是您的特定限定符,不要麻烦在您的焦点中包含其他crud…从这一点来看,您正在查看特定的时间框架…从这一点来看,拥有MyField也将有助于优化GroupBy。键的前两部分/其中,它专门用于筛选您的条件,因此其余部分已按正确顺序保留r分组。我们不能用不完整的查询为您提供完整的答案,请发布WHERE子句的“…”。其他琐碎的选择条件非常重要。索引的使用取决于WHERE
中的所有内容。好的,我们已经更新了问题。我们不能用不完整的查询为您提供完整的答案,请发布WHERE子句的“…”。其他琐碎的选择标准非常重要。索引的使用取决于WHERE
中的所有内容。好的,我已经更新了这个问题。老实说,我不认为在timestamp列中添加索引会有多大帮助。它具有很高的基数,这将导致很大的索引占用。@MikePurcell,这是取决于表和用例。如果表很大,有50个其他列,他需要频繁地进行组计数,那么为它编制索引是值得的。老实说,我不认为在时间戳列中添加索引会有多大帮助。它的基数很高,这将导致索引占用空间很大。@MikePurcell,这是一个在表和用例上悬而未决。如果表很大,有50个其他列,他需要经常进行组计数,那么就值得用磁盘空间对其进行索引。1.似乎一点也不影响它。2.不太可能,最大时间戳通常是当前时间,因此不会真正缩小行数。3.这样做会使e增加一倍执行时间。4.我搞混了,在本例中MyField和MyField3是相同的,而MyField2在本例中的基数是2,因此这并没有真正的帮助。我认为执行时间过长的罪魁祸首实际上是MyField3不在(从另一个表中选择字段)
因为删除操作大大提高了性能。原来我脑子里有几个不同的查询