为查询性能mysql分别保留记录子集

时间:2017-09-08 08:53:46

标签: mysql database query-performance

我有一张包含超过1000万条记录的大表,它会继续增长。我正在对过去24小时的记录执行聚合查询(特定值的计数)。此查询所用的时间将随着表中记录的数量而增加。

我可以限制将这些24小时记录保存在单独的表中并在该表上执行聚合所花费的时间。 mysql是否提供了处理这种情况的任何功能?

表架构和查询供参考:

CREATE TABLE purchases (
    Id int(11) NOT NULL AUTO_INCREMENT, 
    ProductId int(11) NOT NULL, 
    CustomerId int(11) NOT NULL, 
    PurchaseDateTime datetime(3) NOT NULL, 
    PRIMARY KEY (Id), 
    KEY ix_purchases_PurchaseDateTime (PurchaseDateTime) USING BTREE, 
    KEY ix_purchases_ProductId (ProductId) USING BTREE, 
    KEY ix_purchases_CustomerId (CustomerId) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

select COALESCE(sum(ProductId = v_ProductId), 0),
       COALESCE(sum(CustomerId = v_CustomerId), 0)
    into v_ProductCount, v_CustomerCount
    from purchases
    where PurchaseDateTime > NOW() - INTERVAL 1 DAY
      and (   ProductId = v_ProductId
           or CustomerId = v_CustomerId );

2 个答案:

答案 0 :(得分:1)

建立并维护一个单独的Summary table

使用分区,您可能会获得一些小改进,或者您可能没有任何改进。使用汇总表,您可以获得10倍的改进。

摘要表可能有1天的分辨率,或者您可能需要1小时。请提供SHOW CREATE TABLE了解您目前拥有的内容,以便我们详细讨论。

(没有你想要的内置机制。)

答案 1 :(得分:0)

计划A

我会离开

INDEX(PurchaseDateTime, ProductId, CustomerId)

因为查询的其余部分无论如何都会处理它。

然后我会添加

SELECT

将覆盖"覆盖" - 也就是说,整个OR可以在INDEX的BTree中执行。它也会被聚集在一起'在某种意义上,所有所需的数据将连续存储在索引中。是的,日期时间是刻意的。 (v_ProductId对于优化非常麻烦。我不相信优化工具可以做"索引合并联盟"。)

计划B

如果您希望触摸很少的行(因为v_CustomerIdSELECT COALESCE(sum(ProductId = v_ProductId), 0) INTO v_ProductCount FROM purchases WHERE PurchaseDateTime > NOW() - INTERVAL 1 DAY AND ProductId = v_ProductId; SELECT COALESCE(sum(CustomerId = v_CustomerId), 0) INTO v_CustomerCount FROM purchases WHERE PurchaseDateTime > NOW() - INTERVAL 1 DAY AND CustomerId = v_CustomerId; ),那么以下内容可能会更快,尽管更复杂:

INDEX(ProductId, PurchaseDateTime),
INDEX(CustomerId, PurchaseDateTime)

与两者一起:

{{1}}

是的,列的顺序是故意不同的。

原始问题

这两种方法都比单独表格的原始建议更好。这些将数据隔离在索引的一部分(或两个索引)中,从而具有"分离的效果。而这些任务可以帮助您完成任务。