我需要经常获取最近24小时的数据,而且这个查询经常运行。因为这会扫描许多行,所以经常使用它会影响数据库性能。
mysql执行策略在创建的\u at上选取索引,返回大约100000行,然后逐个扫描这些行以筛选customer\u 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
5条答案
按热度按时间cgyqldqp1#
我要做的第一个优化是访问表:
然后,如果查询仍然很慢,我会尝试将您选择的列附加到索引中。例如,如果您正在选择列
order_id
,amount
,和status
:第二种策略可能是有益的,但您需要对其进行测试,以了解它在您的特定情况下带来了哪些性能改进。
第二种策略的最大改进是它只遍历二级索引,避免了遍历回表的主聚集索引(这可能会耗费时间)。
dfddblmv2#
在(customer\u id,created\u at)上创建一个复合索引,而不是在id和created上创建两个单一索引。这样索引引擎就可以同时使用where子句的两个部分,而不只是希望得到一个。直接跳转到客户id,然后直接跳转到所需的日期,然后给出结果。应该很快。
其他后续行动。我听到你关于有多个索引的评论,但是把它们添加到主索引中,比如
(客户id、创建时间、更新时间、完成时间)
然后,在您的查询中,总是可以在where子句中包含一些关于索引的帮助。例如,我不知道你的具体数据。记录是在某个给定点创建的。更新和完成时间将始终在此之后。从创建到完成需要多长时间(最坏的情况下)。。。2天,10天,90天?
再举一个例子,但是如果一个人有1000个订单和相对快速的周转时间,你可以跳转到最近的订单,然后在这个时间段内找到更新的订单。。同样,只需一个选项作为单个索引,而不是3个、4个或更多索引。
bgtovc5b3#
对于此查询:
我的第一个倾向是一个综合指数
(customer_id, created_at)
--正如其他人所建议的那样。但是,您似乎每天都有大量的数据和许多插入。这意味着分区加上索引。适当的分区将在
created_at
,可能是每天,以及user_id
.典型的查询将访问最近的两个分区。因为您的查询集中在最近的数据上,所以这也减少了索引占用的内存,这可能是一个总体好处。
hgqdbh6s4#
似乎您正在处理一个非常快速增长的表,我应该考虑将这个频繁查询移动到冷表或副本。
还有一点是,您是否考虑过按客户id进行分区。我不太了解查询客户id=10背后的业务逻辑。如果是多租户应用程序,请尝试分区。
0g0grzrc5#
这个技巧应该比其他所有答案都好,尽管可能只有一小部分:
而不是
orders
因此被编入索引:执行此操作以将行“聚集”在一起:
然后,您可以选择从
customer_id
根据需要。不管怎样。另一个问题——您将如何处理2万行?这是一个很大的饲料客户,尤其是人类类型。如果你咀嚼它,你不能做一个更复杂的查询,做更多的工作,并返回更少的行?那可能会更快。