Select 在 MySQL InnoDB Table 上查询非常慢 Table 有 160M+ 行

Select Query is very slow on MySQL InnoDB Table having 160M+ rows

下面是我创建的 table 结构和索引。 table 有 160 多万行。

create table test
(
client_id varchar(100),
user_id varchar(100),
ad_id varchar(100),
attr0 varchar(250),
scp_id varchar(250),
attr1 datetime null default null,
attr2 datetime null default null,
attr3 datetime null default null,
attr4 datetime null default null,
sent_date date null default null,
channel varchar(100)
)ENGINE=InnoDB;

CREATE INDEX idx_test_cid_sd ON test (client_id,sent_date);
CREATE INDEX idx_test_uid ON test (user_id);
CREATE INDEX idx_test_aid ON test (ad_id);

下面是我的查询 运行:

select 
 count(distinct user_id) as users
 count(distinct ad_id) as ads
, count(attr1) as attr1
, count(attr2) as attr2
, count(attr3) as attr3
, count(attr4) as attr4
from test
where client_id = 'abcxyz'
and sent_date >= '2017-01-01' and sent_date < '2017-02-01';

问题:上面的查询花费了很多时间超过 1 小时才得到 return 结果。当我看到解释计划时,它正在使用索引并仅扫描 800 万条记录,但奇怪的问题是 return 结果花费了 1 个多小时。

谁能告诉我这里出了什么问题或对优化部分有什么建议吗?

您可以添加一个 covering index,仅包含 where 子句的列,但也包含结果的选定列。通过这种方式,查询可以从索引中读取整个结果,而不必读取一行。 where 子句中使用的列需要保留为索引的第一列,以便此索引可用于 where 限制。

CREATE INDEX idx_test_cid_sd_cover_all ON test 
    (client_id, sent_date, user_id, ad_id, attr1, attr2, attr3, attr4);

但是这个索引将比您现有的索引更大,因为几乎所有 table 的数据都将作为副本存在于索引中。

  • 缩小 table 以减少对 I/O 的需求。这包括规范化(在可行的情况下)。为各种 ID 使用合理大小的 AUTO_INCREMENT,而不是 VARCHAR。如果您能解释这些 varchars,我可以评估这是否实用以及您可能获得多少好处。

  • 有一个PRIMARY KEY。 InnoDB 不喜欢没有。 (这对特定问题没有帮助。如果列的某些组合是 UNIQUE,则将其设为 PK。如果不是,请使用 id INT UNSIGNED AUTO_INCREMENT;它不会 运行 out ids 直到40亿后

  • 更改 PRIMARY KEY 以使查询 运行 更快。 (虽然可能不比 Simulant 的 "covering" 索引快。)但它不会那么笨重:

假设你加上id .. AUTO_INCREMENT,那么:

PRIMARY KEY(client_id, sent_date, id),
INDEX(id)

数据有多大(GB)?指数?您 可能 正处于 "too big to cache" 的风口浪尖,支付更多 RAM 可能会有所帮助。

  • 摘要 table 适合 COUNT,但不适合 COUNT(DISTINCT ...)。也就是说,计数可以在几秒钟内完成。对于 Uniques,请参阅 my blog。 las,它相当粗略;请求帮忙。它提供与 COUNT 一样高效的汇总 COUNT(DISTINCT...),但有 1-2% 的误差。

摘要要点 table:PRIMARY KEY(client_id, day) 包含每天计数的列。然后获取一个月的值是 SUMming 31 天的计数。非常快。更多关于 Summary Tables.