MySql查询在实时中超时,但在本地未超时

时间:2018-07-30 23:06:35

标签: mysql innodb database-optimization

我们正在使用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。

2 个答案:

答案 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在哪个表中?