Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/80.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表中的查询?_Mysql_Sql_Query Optimization - Fatal编程技术网

如何在没有任何连接的情况下优化大型MySQL表中的查询?

如何在没有任何连接的情况下优化大型MySQL表中的查询?,mysql,sql,query-optimization,Mysql,Sql,Query Optimization,如何从单个大型ish表(约75M行)优化此查询 我为一组特定的类提取最近的10k记录,以便在更大的导入脚本中快速知道它们是否已经存在 我想我已经建立了适当的索引,但是这个查询会持续5-50秒 如果你还需要什么,请告诉我 EXPLAIN SELECT log_id FROM score WHERE class_id IN (17,395) ORDER BY date_reverse LIMIT 10000;

如何从单个大型ish表(约75M行)优化此查询

我为一组特定的类提取最近的10k记录,以便在更大的导入脚本中快速知道它们是否已经存在

我想我已经建立了适当的索引,但是这个查询会持续5-50秒

如果你还需要什么,请告诉我

EXPLAIN
    SELECT
        log_id
    FROM
        score
    WHERE
        class_id IN (17,395)
    ORDER BY date_reverse
    LIMIT 10000;

*** row 1 ***
          table:  score
           type:  range
  possible_keys:  class_id,score_multi_2,class_id_date_reverse,score_multi_5
            key:  class_id_date_reverse
        key_len:  4
            ref:  NULL
           rows:  1287726
          Extra:  Using where; Using index; Using filesort

CREATE TABLE `score` (
  `log_id` bigint(20) NOT NULL,
  `profile_id` bigint(20) DEFAULT NULL,
  `date` datetime DEFAULT NULL,
  `class_id` int(11) NOT NULL,
  `score` float(10,6) DEFAULT NULL,
  `score_date` datetime DEFAULT NULL,
  `process_date` datetime DEFAULT NULL,
  `status_type_id` int(3) NOT NULL DEFAULT '0',
  `date_reverse` int(11) DEFAULT NULL,
  UNIQUE KEY `unique_key` (`log_id`,`class_id`),
  KEY `class_id` (`class_id`),
  KEY `profile_id` (`profile_id`),
  KEY `date` (`date`),
  KEY `score` (`score`),
  KEY `status_type_id` (`status_type_id `),
  KEY `status_type_id_date` (`status_type_id`,`date`),
  KEY `class_status_type_id_date_log_id` (`class_id`,`status_type_id`,`date`,`log_id`),
  KEY `date_reverse` (`date_reverse`),
  KEY `class_id_date_reverse` (`class_id`,`date_reverse`),
  KEY `date` (`date`),
  KEY `class_id_date_reverse_log_id` (`class_id`,`date_reverse`,`log_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

我猜运行此查询的最快方法是咬紧牙关,允许对20000行进行排序。我想提出的问题是:

SELECT *
FROM ((SELECT log_id
       FROM score
       WHERE class_id = 17
       ORDER BY date_reverse
       LIMIT 10000
      ) UNION ALL
      (SELECT log_id
       FROM score
       WHERE class_id = 395
       ORDER BY date_reverse
       LIMIT 10000
      )
     ) s
ORDER BY date_reverse
LIMIT 10000;

对于这个查询,您需要在
分数(class\u id,date\u reverse,log\u id)
上的复合索引。每个子查询都应该非常有效地使用这个索引。但是,最后的排序需要使用文件排序。

我怀疑Gordon是对的,但我可能也会尝试其他方法。将您的唯一密钥更改为主键,并将顺序颠倒为(
class\u id
,log\u id`)。然后尝试像以前一样运行查询。假设这是在Innodb存储引擎上,MySQL将在每个二级索引中包含主键值,使您的日期反向索引有效(class\u id,log\u id)+日期反向。我不确定这是否会对优化器产生影响,但也有可能。我至少会好奇地试一试。谢谢@evanv,你的意思是:
altertablescore-DROP-UNIQUE-KEY,ADD-PRIMARY-KEY(class\u-id,log\u-id)@Ryan,是的。同样,我不确定这是否会有帮助。但我愿意试一试。另外,如果你尝试一下的话,把你的class_id键改为log_id。一天结束时,Gordon和evan提出的解决方案对结果时间几乎没有影响。我接受Gordon的答案,因为我最终归档了这个表的很大一部分,以使其工作,并且不再有能力测试其他解决方案。
SELECT *
FROM ((SELECT log_id
       FROM score
       WHERE class_id = 17
       ORDER BY date_reverse
       LIMIT 10000
      ) UNION ALL
      (SELECT log_id
       FROM score
       WHERE class_id = 395
       ORDER BY date_reverse
       LIMIT 10000
      )
     ) s
ORDER BY date_reverse
LIMIT 10000;