首先İ使用wherehas,但后来我决定使用这种方式。这种方法比以前的方法效果好,但我不满意。查询响应时间为873ms。表中有400k+数据
select count(*) as aggregate
from `orders`
where (`pickup_address_id` in (
select `id`
from `addresses`
where `region_id` = 12)
or `delivery_address_id` in (
select `id`
from `addresses`
where `region_id` = 12)
) and `orders`.`status` = 2
试试这个:
select count(distinct o.`id`) as aggregate
from `orders` o
inner join `addresses` a ON a.`id` IN (o.`pickup_address_id`, o.`delivery_address_id`)
AND a.`region_id` = 12
where o.`status` = 2
另外:
SELECT count(distinct id) as aggregate
FROM (
select o.`id`
from `orders` o
inner join `addresses` a ON a.`id` = o.`pickup_address_id`
AND a.`region_id` = 12
where o.`status` = 2
UNION
select o.`id`
from `orders` o
inner join `addresses` a ON a.`id` = o.`delivery_address_id`
AND a.`region_id` = 12
where o.`status` = 2
) t
但是我不知道在不到一秒的时间内查看400K行会有多大的提高。
首先,您可以尝试使用Common Table Expression
WITH CTE(id) AS (
SELECT id
FROM addresses
WHERE region_id = 12
)
此CTE将计算一次。
其次,在cte
中存在pickup_address_id
和delivery_address_id
的条件下,从orders
表中得到与cte
联接的行数。
WITH CTE(id) AS (
SELECT id
FROM addresses
WHERE region_id = 12
)
SELECT COUNT (*)
FROM orders
CROSS JOIN CTE ON CTE.id = orders.delivery_address_id
OR CTE.id = orders.pickup_address_id
最后,通过status = 2
添加过滤器,查询将像
WITH CTE(id) AS (
SELECT id
FROM addresses
WHERE region_id = 12
)
SELECT COUNT (*)
FROM orders
CROSS JOIN CTE ON CTE.id = orders.delivery_address_id
OR CTE.id = orders.pickup_address_id
WHERE orders.status = 2
还应该有以下索引:
addresses
:
INDEX (region_id)
orders
table:
INDEX (pickup_address_id),
INDEX (delivery_address_id),
INDEX (status)
试一试。
对于空表,我得到了这个
Schema (MySQL v8.0)create table addresses (
id int primary key,
region_id int not null,
index(region_id)
);
create table orders (
id int primary key,
pickup_address_id int,
delivery_address_id int,
status int not null,
index (pickup_address_id),
index (delivery_address_id),
index(status),
foreign key (pickup_address_id) references addresses(id),
foreign key (delivery_address_id) references addresses(id)
);
查询# 1
explain with cte(id) as (
select id from addresses where region_id = 12)
select count(*) from orders
cross join cte on cte.id = orders.delivery_address_id
or cte.id = orders.pickup_address_id
where status = 2;
<表类>id select_type 表分区 类型 possible_keys 键 key_len ref 行 过滤额外 tbody><<tr>1 简单 订单 ref pickup_address_id, delivery_address_id、地位 状态 4 const 1 100 1简单 地址 ref 小学,region_id region_id 4 const 1 100 使用的地方;使用指数 表类>