我目前使用以下查询,由于数据量大约需要8分钟才能返回结果(大约14个月)。有没有办法让我加快速度呢?
有问题的数据库是带有InnoDb引擎的MySQL
select
CUSTOMER as CUST,
SUM(IF(PAGE_TYPE = 'C',PAGE_TYPE_COUNT,0)) AS TOTAL_C,
SUM(IF(PAGE_TYPE = 'D',PAGE_TYPE_COUNT,0)) AS TOTAL_D
from
PAGE_HITS
where
EVE_DATE >= '2016-01-01' and EVE_DATE <= '2016-01-05'
and SITE = 'P'
and SITE_SERV like 'serv1X%'
group by
CUST
数据分区为6个月。进入where子句的每一列都被编入索引。有一些指数&amp;将是一个列在这里的大清单。因此,只需用文字进行总结。对于此查询,EVE_DATE + PAGE_TYPE_COUNT
是复合索引之一&amp; CUST + SITE_SERV + EVE_DATE
,EVE_DATE + SITE_SERV
,EVE_DATE + SITE
,
主键实际上是一个虚拟自动增量编号。它不是老实说的。我无法访问解释计划。我会看到我能为此做些什么。
我很感激任何帮助来改善这一点。
答案 0 :(得分:3)
我没有数据,所以我无法测试速度,但我认为它会更快。
select
CUSTOMER as CUST,
SUM(PAGE_TYPE_COUNT * (PAGE_TYPE = 'C')) AS TOTAL_C,
SUM(PAGE_TYPE_COUNT * (PAGE_TYPE = 'D')) AS TOTAL_D
from
PAGE_HITS
where
EVE_DATE >= '2016-01-01' and EVE_DATE <= '2016-01-05'
and SITE = 'P'
and SITE_SERV like 'serv1X%'
group by
CUST
在MySql 5.6
上我的小提琴工作得很好答案 1 :(得分:2)
主要的优化因素是索引。一个应尽可能与您的查询匹配,例如:
EVE_DATE, SITE, CUST, SITE_SERV
顺序很重要,至少对于SITE_SERV作为最后一个值;当您在其上使用LIKE
时,您将不会使用完整值,这会降低下一列的索引效率。
通过删除IF
并返回类型和计数,您可能也会获得一点点;也许你可以在前端应用程序中处理/格式化这个值?
无论如何,您应该首先使用EXPLAIN
分析当前查询,看看出了什么问题。如果你不能,你可以尝试在本地数据库上复制结构,索引和一些虚拟数据,那里的数量是无关紧要的。
答案 2 :(得分:2)
好的,由于表范围分区在EVE_DATE,DBMS应该很容易看到要读取的分区。因此,所有关于使用什么索引的都是。
您检查了一列是否相等(SITE = 'P'
)。这应该在您的索引中排在第一位。然后,您可以按我猜的顺序添加EVE_DATE
和SITE_SERV
。因此,您的索引应该能够尽快找到有问题的表记录。
但是,如果将查询中使用的其他字段添加到索引中,则甚至不必读取该表,因为索引本身中的所有数据都是可用的:
create index on page_hits(site, eve_date, site_serv, customer, page_type, page_type_count);
如果我没弄错的话,这应该是您查询的最佳索引。
答案 3 :(得分:2)
添加以下两个索引:
INDEX(site, date)
INDEX(site, site_serv)
优化器将查看统计信息并在它们之间进行选择。粗略地说,如果“P”和“P”的行数较少,那么第一个会更好。该范围内的日期,而不是'P'和'serv1X%'。
是的,Thorsten可能更好的“覆盖”索引,但它有更多的字段,而不是我想放入索引。
PARTITIONing
可能帮助。但肯定有太少的信息要说。分区可能有帮助的原因是你有一个“二维”查找 - 一个日期范围和'serv1X%'。您需要在date或site_serv上进行分区,然后将PRIMARY KEY(site, ..., ...)
与(date或site_serv)中的另一个作为第二列进行分区。其余列需要包括分区键和一些列以使其唯一。这太乱了,我不想考虑它。