Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 使用WHERE和GROUP BY进行查询时使用的最有效索引?_Mysql_Sql_Optimization_Indexing_Query Optimization - Fatal编程技术网

Mysql 使用WHERE和GROUP BY进行查询时使用的最有效索引?

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 >

我有一个约700万行的表,我一直在运行这类查询:

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不在(从另一个表中选择字段)
    因为删除操作大大提高了性能。原来我脑子里有几个不同的查询