我需要频繁获取最近24小时的数据,并且此查询频繁运行。 由于此操作会扫描许多行,因此经常使用它会影响数据库性能。
MySql执行策略在created_at上选择索引,并返回大约1,00,000行。然后逐行扫描这些行以过滤customer_id = 10,我的最终结果为20000行。
如何优化此查询?
explain SELECT *
FROM `order`
WHERE customer_id = 10
and `created_at` >= NOW() - INTERVAL 1 DAY;
id : 1
select_type : SIMPLE
table : order
partitions : NULL
type : range
possible_keys : idx_customer_id, idx_order_created_at
key : idx_order_created_at
key_len : 5
ref : NULL
rows : 103357
filtered : 1.22
Extra : Using index condition; Using where
答案 0 :(得分:1)
不是在ID和Created上创建两个单一索引,而是在(customer_id,created_at)上创建了一个综合索引。这样,索引引擎可以使用where子句的两个部分,而不仅仅是希望获得一个。向右跳到客户ID,然后直接跳到所需日期,然后给出结果。它应该非常快。
其他后续行动。 我听到了您对拥有多个索引的评论,但将其添加到主要索引中,例如
(customer_id,created_at,updated_at,completion_time)
然后,在您的查询中,总可以在where子句中为索引提供一些帮助。例如,我不知道您的具体数据。在某个给定点创建一条记录。之后,更新和完成时间将始终在此之后。从创建到完成需要多长时间(最坏的情况)... 2天,10天,90天?
where
customerID = ?
AND created_at >= date - 10 days
AND updated_at >= date -1
同样,这只是一个例子,但是如果一个人有1000个订单并且周转时间相对较快,则可以跳到最近的那些,然后找到在该时间段内更新的那些。单一索引与3、4个或更多索引。
答案 1 :(得分:1)
我要做的第一个优化是对表的访问:
create index ix1 on `order` (customer_id, created_at);
然后,如果查询仍然很慢,我将尝试将您选择的列追加到索引。例如,如果要选择列order_id
,amount
和status
:
create index ix1 on `order` (customer_id, created_at,
order_id, amount, status);
第二种策略可能是有益的,但是您需要对其进行测试,以了解在特定情况下它可以带来哪些性能改进。
第二种策略的最大改进是,它避免回溯到表的主聚集索引(这可能是耗时的),从而仅遍历辅助索引。
答案 2 :(得分:0)
似乎您正在处理一个快速增长的表,我应该考虑将此频繁查询移至冷表或副本。
还有一点,您是否考虑过按customer_id进行分区。我不太了解查询customer_id = 10的背后的业务逻辑。如果它是多租户应用程序,请尝试分区。
答案 3 :(得分:0)
对于此查询:
SELECT o.*
FROM `order` o
WHERE o.customer_id = 10 AND
created_at >= NOW() - INTERVAL 1 DAY;
我的第一个倾向将是(customer_id, created_at)
上的综合索引-正如其他人所建议的那样。
但是,您每天似乎有很多数据和许多插入内容。这表明分区加索引。适当的分区可能位于created_at
上,并且可能每天都在user_id
的索引上。
典型查询将访问两个最新分区。因为您的查询集中在最近的数据上,所以这也减少了索引占用的内存,这可能是一个整体好处。
答案 4 :(得分:0)
该技术应该比所有其他答案都要好,尽管可能只是少量:
代替索引orders
:
PRIMARY KEY(order_id) -- AUTO_INCREMENT
INDEX(customer_id, ...) -- created_at, and possibly others
执行此操作以将行“聚集”在一起:
PRIMARY KEY(customer_id, order_id)
INDEX (order_id) -- to keep AUTO_INCREMENT happy
然后,根据需要,您可以根据需要选择更多以customer_id
开头的索引。是否。
另一个问题-20K行将如何处理?可以给客户带来很多,尤其是人类。如果您随后进行猛烈的修改,是否可以进行更复杂的查询,该查询执行的工作更多并且返回的行更少? 那可能会更快。