[英]Select Query is very slow on MySQL InnoDB Table having 160M+ rows
以下是我创建的表结构和索引。 该表有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小时才能返回结果。 当我看到解释计划时,它正在使用索引并仅扫描800万条记录,但是奇怪的问题是返回结果要花费超过1个小时的时间。
谁能告诉我这里出了什么问题或在优化方面有何建议?
缩小表以减少对I / O的需求。 这包括规范化(在可行的情况下)。 对各种id使用合理大小的AUTO_INCREMENT
代替VARCHAR
。 如果您可以解释这些varchar,我可以评估这是否可行以及您将获得多少收益。
有一个PRIMARY KEY
。 InnoDB不喜欢没有一个。 (这将不会解决特定问题。如果某些列组合是UNIQUE
,则使它成为PK。否则,请使用id INT UNSIGNED AUTO_INCREMENT
;直到40亿之后,ID才会用完。
更改PRIMARY KEY
以使查询运行更快。 (尽管可能不比Simulant的“ covering”索引快。)但是它的体积要小一些:
假设您添加id .. AUTO_INCREMENT
,然后:
PRIMARY KEY(client_id, sent_date, id),
INDEX(id)
数据有多少(GB)? 指标? 您可能正处于“太大而无法缓存”的风口浪尖,而购买更多的RAM可能会有所帮助。
COUNT
,但不适用于COUNT(DISTINCT ...)
。 也就是说,计数可以在几秒钟内完成。 有关唯一性,请参阅我的博客 。 it,这有点粗略。 请求帮忙。 它提供的COUNT(DISTINCT...)
滚动效果与COUNT
一样有效,但是错误为1-2%。 摘要表的要点: PRIMARY KEY(client_id, day)
其中包含每天计数的列。 然后获得一个月的值就是对31天的计数SUMming
。 非常快。 有关汇总表的更多信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.