我们正在使用MySQL InnoDB。
我们有一个类似这样的查询。
在我们的实时环境中,此查询花费了超过30秒的时间。
select count(*) as aggregate
from `parents`
where exists (
SELECT *
from `childs`
where `parents`.`id` = `childs`.`parent_id`
and exists (
SELECT *
from `users`
where `childs`.`user_id` = `users`.`id`
and `id` = '123456' )
and `status` = 'OK' )
因此,我们已经导出了整个数据库并将其导入到我们本地的mysql数据库中。 令人惊讶的是,几乎要花一秒钟的时间才能获得相同的查询结果。
因此,我们怀疑该表未进行优化,因此我们执行了以下操作。
optimize table users;
optimize table parents;
optimize table childs;
不幸的是,查询速度并没有提高。
谁能看到可能出问题的地方?
为什么在本地(具有完全相同的结构数据)中的导出/导入几乎具有即时查询,而实时完成却要花费近30-60秒的时间?
本地和现场的EXPLAIN显示不同, 其中一个与父表和子表相关的可能键的DEPENDENT子查询之一
Using where; FirstMatch(closing_batches)
但是现场直播仅显示Using where
,而没有FirstMatch。
答案 0 :(得分:1)
实际上,您可能甚至可以不使用父表或用户表而从单个查询中获取所有数据-如果“状态”字段位于子表中。
来自基本的及物关联,
if A = B and B = C, then A = C.
您要按ID从子级加入用户,然后查看User ID =“ 123456”。
这与只询问Childs.User_ID =“ 123456”相同。
同样,从通过Child.Parent_ID加入到父级的Child中,您的查询似乎试图获取与给定子级相关联的不同父级ID的计数。
因此,以下内容应该能够满足您的需求。
select
count( distinct c.Parent_id ) Aggregate
from
childs c
where
c.user_id = '123456'
AND c.status = 'OK'
如果状态字段位于PARENT表上,则需要加入该字段
select
count( distinct c.Parent_id ) Aggregate
from
childs c
join parents p
on c.parent_id = p.id
AND p.status = 'OK'
where
c.user_id = '123456'
为了提高性能,我还要在(user_id,parent_id)的childs表上有一个索引。这也可以大大优化查询。
答案 1 :(得分:0)
这可能是等效的:
select count(*) as aggregate
from `parents` AS p
where exists (
SELECT *
from `childs` AS c
JOIN users AS u ON c.user_id = u.id
WHERE c.user_id = 123456
AND p.`id` = c.`parent_id`
and `status` = 'OK'
)
OPTIMIZE TABLE
很少有用。
status
在哪个表中?