我在rental_schedules 表中有大约400 万条记录和大约1k 前提,获取数据最多需要1.5 秒。现在是时候了,或者我可以以某种方式优化更多?这是我的查询:
select
count(*) as aggregate
from
`premises`
where
exists (
select
*
from
`rental_schedules`
where
`premises`.`id` = `rental_schedules`.`premises_id`
and `date` >= '2021-07-01'
and `public_enterprise` = 0
and `rental_schedule_status` = 1
)
and exists (
select
id
from
rental_schedules
where
premises.id = rental_schedules.premises_id
and public = 1
and public_enterprise = 0
)
这是我的前提表索引:
PRIMARY KEY (`id`),
KEY `premises_institution_id_foreign` (`institution_id`),
KEY `premises_responsible_user_id_foreign` (`responsible_user_id`),
KEY `premises_cover_type_id_foreign` (`cover_type_id`),
KEY `premises_premises_type_id_foreign` (`premises_type_id`),
CONSTRAINT `premises_cover_type_id_foreign` FOREIGN KEY (`cover_type_id`) REFERENCES `cover_types` (`id`),
CONSTRAINT `premises_institution_id_foreign` FOREIGN KEY (`institution_id`) REFERENCES `institutions` (`id`) ON DELETE CASCADE,
CONSTRAINT `premises_premises_type_id_foreign` FOREIGN KEY (`premises_type_id`) REFERENCES `premises_types` (`id`),
CONSTRAINT `premises_responsible_user_id_foreign` FOREIGN KEY (`responsible_user_id`) REFERENCES `dashboard_users` (`id`)
这是我的租赁时间表表索引:
PRIMARY KEY (`id`),
KEY `rental_schedules_date_index` (`date`),
KEY `rental_schedules_week_day_id_foreign` (`week_day_id`),
KEY `rental_schedules_rental_schedule_status_foreign` (`rental_schedule_status`),
KEY `rental_schedules_contract_id_foreign` (`contract_id`),
KEY `rental_schedules_bill_id_foreign` (`bill_id`),
KEY `rental_schedules_accordion_id_index` (`accordion_id`),
KEY `premises_search` (`premises_id`,`rental_schedule_status`,`date`,`public_enterprise`),
KEY `rental_schedules_search` (`premises_id`,`public`,`public_enterprise`,`rental_schedule_status`),
KEY `rental_schedules_search_with_date` (`premises_id`,`public`,`public_enterprise`,`rental_schedule_status`,`date`),
CONSTRAINT `rental_schedules_bill_id_foreign` FOREIGN KEY (`bill_id`) REFERENCES `bills` (`id`) ON DELETE SET NULL,
CONSTRAINT `rental_schedules_contract_id_foreign` FOREIGN KEY (`contract_id`) REFERENCES `contracts` (`id`) ON DELETE SET NULL,
CONSTRAINT `rental_schedules_premises_id_foreign` FOREIGN KEY (`premises_id`) REFERENCES `premises` (`id`),
CONSTRAINT `rental_schedules_rental_schedule_status_foreign` FOREIGN KEY (`rental_schedule_status`) REFERENCES `rental_schedule_statuses` (`id`),
CONSTRAINT `rental_schedules_week_day_id_foreign` FOREIGN KEY (`week_day_id`) REFERENCES `week_days` (`id`)
提前感谢您的帮助!
答案 0 :(得分:1)
我可能忽略了它,但我认为这里不需要 2 个不同的 EXISTS 运算符。因此您的查询可以优化为 -
select count(*) as aggregate
from `premises`
where exists (select null
from `rental_schedules`
where `premises`.`id` = `rental_schedules`.`premises_id`
and `date` >= '2021-07-01'
and `public_enterprise` = 0
and `rental_schedule_status` = 1
and public = 1);
答案 1 :(得分:1)
SELECT COUNT(*) AS aggregate
FROM premises AS p
JOIN rental_schedules AS rs ON p.`id` = rs.`premises_id`
WHERE `date` >= '2021-07-01'
AND `public_enterprise` = 0
AND `rental_schedule_status` = 1
AND public = 1;
rental_schedules
上的这个“复合”和“覆盖”索引会有所帮助:
INDEX(public_enterprise, rental_schedule_status, public, date, premises_id)
列的顺序很重要——首先是 =
,然后是范围 >=
,最后是“覆盖”所需的任何其他内容。
如果所有这些 id 都是 BIGINT
,请注意每个 id 占用 8 个字节,并且大小可能有点过大。