【问题标题】:Mysql execution time is too longmysql执行时间过长
【发布时间】:2018-01-19 18:37:47
【问题描述】:

我的表中有 200 万条记录。当我执行一个包含 3 个where condition 的查询时,响应时间太长。

查询

SELECT COUNT(*) 
  FROM `table` 
 WHERE DATE(`created_at`) = '2017-08-11' 
   AND `type` in (4,13,15) 
   AND `status` = 1

执行时间:3秒

如何减少此查询或任何类似查询的执行时间?

编辑

表架构

CREATE TABLE `transactions` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `type` int(11) NOT NULL,
  `status` int(11) NOT NULL DEFAULT '2',
  `created_at` timestamp NULL DEFAULT NULL,
  ...
  PRIMARY KEY (`id`),
  KEY `query` (`created_at`,`type`,`status`),
  KEY `query2` (`status`,`type`)

我不知道我的索引是否正确

【问题讨论】:

  • 你的桌子怎么样?我认为您缺少一些indexes
  • @Fotis 它有 41 列

标签: mysql


【解决方案1】:

为了让这个查询运行得更快,你需要给你的表添加索引。

首先通过在SELECT 之前添加EXPLAIN 来运行相同的查询。这将使您对检查的行数、关键基数等有一个很好的概述。

如果这是您使用的标准查询,我建议您对所有 3 列使用 add an index。如果您打算单独查询列,您可以为需要查询的每一列添加索引,但不要过度,因为表会变慢。

如果你在添加索引后运行EXPLAIN,我猜你会得到检查的行数显着减少。

如果您的表已经有索引,您可以使用USE INDEX 提示来提示 MySQL 服务器。

【讨论】:

    【解决方案2】:

    你可能需要一个适当的索引,例如:

      create index  my_new_index on `table`  ( date(`created_at`), `type`,  `status` );
    

    【讨论】:

      【解决方案3】:

      尝试分隔IN 子句。我亲身经历过IN 子句使查询变慢,因为内部MySQL 假定全表扫描并在某些情况下忽略索引。此外,DATE(created_at) 将完全忽略索引,因为它是按日期时间编入索引的。

      您可以尝试以下UNION 查询并希望它加快输出速度:

      SELECT SUM(total) AS total
        FROM (
          SELECT COUNT(*) AS total
            FROM `table` 
          WHERE `created_at` BETWEEN '2017-08-11 00:00:00' AND  '2017-08-11 23:59:59'
            AND `type` = 4 
            AND `status` = 1
          UNION
          SELECT COUNT(*) AS total
            FROM `table` 
          WHERE `created_at` BETWEEN '2017-08-11 00:00:00' AND  '2017-08-11 23:59:59'
            AND `type` = 13 
            AND `status` = 1
          UNION
          SELECT COUNT(*) AS total
            FROM `table` 
          WHERE `created_at` BETWEEN '2017-08-11 00:00:00' AND  '2017-08-11 23:59:59'
            AND `type` = 15 
            AND `status` = 1
        ) z;
      

      如果您的现有系统可行,您还可以添加仅包含 date 的列或从 created_at 中删除时间并将其存储在新的 time 列中。

      【讨论】:

      • (DATE(`created_at`),`type`,`status`) 有语法错误
      • 对不起我的错。工作忙,匆忙回答。没有注意到索引错误。已经更新了我的帖子。不要改变你的索引。已修改查询。试试看。
      • 很高兴我能帮上忙 :)
      【解决方案4】:

      替换

      密钥query (created_at,type,status),

      密钥query2 (status,type),

      密钥created_atcreated_at),

      密钥type (type),

      密钥statusstatus),

      我认为它会变得更快。此外,如果可能的话,您必须将类型和状态的数据类型更改为 tinyint、smallint,并且应该添加无符号约束,它永远不是有符号值。

      【讨论】:

        猜你喜欢
        • 2023-03-16
        • 1970-01-01
        • 1970-01-01
        • 2012-03-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-22
        • 2021-10-19
        相关资源
        最近更新 更多