选择 Count on Big table 需要 15 分钟

1 mysql mysql-workbench amazon-rds

我尝试使用 MySql 5.5 和工作台 6.2 在表上运行 select Count ,其中包含 16M 行。查询运行近 1000sec 。正常吗?查询:

SELECT COUNT(1) FROM My_Table
Run Code Online (Sandbox Code Playgroud)

当我运行解释时,我看到 mysql 使用 pk 索引。表中没有其他索引或唯一值。我知道我可以使用 ALL_TABLES 中的估计,但我需要准确的数字。你有什么想法 ?


  • 数据库位于 AMAZON AWS - RDS 上,我使用的是默认参数组,您有什么建议要做的更改吗?

谢谢

spe*_*593 5

是的,这可能是正常的。对于“大表”,您可能需要执行大量 I/O(除非您使用 InnoDB 并且分配了一个巨大的缓冲池。)

除非您为 Amazon Provisioned IOPS 付费,否则您的 I/O 速率在共享卷上会受到一定的限制。

http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Storage.html

因此,有两种解决该问题的基本方法:1) 提高从存储执行 I/O 的速率(即为预置 IOPS 付费),以及 2) 重新组织您的数据,以便请求不需要那么多输入/输出。这将在某种程度上取决于您使用的存储引擎(MyISAM、InnoDB 或其他东西),但设计目标是相同的,获得 MySQL 可以扫描的小得多的索引,而不是扫描整个表。使用 EXPLAIN 来确定 MySQL 正在使用的执行计划,它是否将使用您的索引。

此外,您可能会考虑实施更高级的方法,例如,如果表中有很大一部分是“静态”历史记录,则这些行的计数不会改变。分别获取这些行的计数,并存储该结果。

例如,在给定值之前具有日期列的所有行......获取该计数并将其存储在一个小表中。这只需要做一次:

 CREATE TABLE my_counts (before_dt DATE, mycount BIGINT); 
 INSERT INTO my_counts (before_dt, mycount) 
 SELECT '2014-11-01' AS before_dt, COUNT(1) AS mycount
  FROM mytable t 
 WHERE t.dt < '2014-11-01';
Run Code Online (Sandbox Code Playgroud)

然后,要获得“最新”计数,您可以引用该存储值,然后您只需要获取未包含在该计数中的行数。dt列上的索引将是合适的。结合以下结果:

SELECT COUNT(1)
  FROM my_table t
 WHERE t.dt >= '2014-11-01' 
Run Code Online (Sandbox Code Playgroud)

结果来自:

SELECT mycount
  FROM my_counts c
 WHERE c.before_dt = '2014-11-01' 
Run Code Online (Sandbox Code Playgroud)

也就是说,您可以忍受表的一部分的“陈旧”缓存计数。