MySQL简单选择-15秒执行时间-700万行

时间:2019-03-07 16:00:56

标签: mysql optimization

我有一个包含700万行(每月将增长1000万)用户流量的mysql表,我需要对其进行实时分析。该表有多个列,但结果集中只需要一列。

这是查询:

SELECT DISTINCT visitor 
FROM traffic 
WHERE `visited` < '2019-03-01' AND `client_id` = 1 AND `country` IS NOT NULL

此查询需要15秒钟来执行,目前要处理700万行。我在visitorvisitedclient_idcountry上有单独的索引,在[visitedclient_id和{ {1}}]。

所有索引都不是唯一的,也不是唯一的。

你们能想到我可以减少此查询执行时间的任何方式吗?

2 个答案:

答案 0 :(得分:0)

在这个答案中,我将假设访问的是文本数据,例如varchar,因为我们看到client_id是数字,并且在国家(地区)的情况下,我们只想查看它是否具有值。如果假设访问的文本是正确的,则解决方案是将其类型更改为DATE,DATETIME或TIMESTAMP。由于在这种情况下我们似乎对时间不感兴趣,因此拥有DATE列应该是最热门的候选人。

解决方案(确保涉及交易):

  1. 在表中创建一个访问过的具有相同类型的temp_visited列

  2. 将访问的值复制到temp_visited

  3. 将已访问值设置为null或删除已访问列(无论您需要什么)

  4. 确保您拥有DATE类型的访问列

  5. 通过将文本值转换为DATE将值从temp_visited复制到Visited中

  6. 删除临时访问的列

答案 1 :(得分:0)

数据仓库通常会请求汇总表。

如果您构建并维护包含以下列的摘要表,则该查询(或者更确切地说是打入摘要表的变体)的运行速度会大大提高:

  • visited-到一天(或一个月?)
  • country-也许把那些没有国家的人排除在外?
  • client_id
  • visitor
  • COUNT(*)
  • 也许SUM()是什么东西?

对于PARTITIONing,如果您要清除“旧”行,可能有用。

对于当前查询,最佳索引将是

INDEX(client_id, visited,   -- this much will be used in the `WHERE`
      country, visitor)     -- to make the index "covering"

单列索引实际上将毫无用处。由于“覆盖”,我的4列索引将明显优于任何3列索引。这意味着查询可以在索引内部运行,而不必到达数据的BTree。