优化sql以获取1天的数据

uqjltbpv  于 2021-06-20  发布在  Mysql
关注(0)|答案(5)|浏览(294)

我需要经常获取最近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
cgyqldqp

cgyqldqp1#

我要做的第一个优化是访问表:

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);

第二种策略可能是有益的,但您需要对其进行测试,以了解它在您的特定情况下带来了哪些性能改进。
第二种策略的最大改进是它只遍历二级索引,避免了遍历回表的主聚集索引(这可能会耗费时间)。

dfddblmv

dfddblmv2#

在(customer\u id,created\u at)上创建一个复合索引,而不是在id和created上创建两个单一索引。这样索引引擎就可以同时使用where子句的两个部分,而不只是希望得到一个。直接跳转到客户id,然后直接跳转到所需的日期,然后给出结果。应该很快。
其他后续行动。我听到你关于有多个索引的评论,但是把它们添加到主索引中,比如
(客户id、创建时间、更新时间、完成时间)
然后,在您的查询中,总是可以在where子句中包含一些关于索引的帮助。例如,我不知道你的具体数据。记录是在某个给定点创建的。更新和完成时间将始终在此之后。从创建到完成需要多长时间(最坏的情况下)。。。2天,10天,90天?

where
       customerID = ?
   AND created_at >= date - 10 days
   AND updated_at >= date -1

再举一个例子,但是如果一个人有1000个订单和相对快速的周转时间,你可以跳转到最近的订单,然后在这个时间段内找到更新的订单。。同样,只需一个选项作为单个索引,而不是3个、4个或更多索引。

bgtovc5b

bgtovc5b3#

对于此查询:

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 .
典型的查询将访问最近的两个分区。因为您的查询集中在最近的数据上,所以这也减少了索引占用的内存,这可能是一个总体好处。

hgqdbh6s

hgqdbh6s4#

似乎您正在处理一个非常快速增长的表,我应该考虑将这个频繁查询移动到冷表或副本。
还有一点是,您是否考虑过按客户id进行分区。我不太了解查询客户id=10背后的业务逻辑。如果是多租户应用程序,请尝试分区。

0g0grzrc

0g0grzrc5#

这个技巧应该比其他所有答案都好,尽管可能只有一小部分:
而不是 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 根据需要。不管怎样。
另一个问题——您将如何处理2万行?这是一个很大的饲料客户,尤其是人类类型。如果你咀嚼它,你不能做一个更复杂的查询,做更多的工作,并返回更少的行?那可能会更快。

相关问题