带有左联接的MySQL查询-NULL记录被隐式类型转换

时间:2018-07-26 14:45:55

标签: mysql left-join

只需调查一个MySQL查询,该查询返回的记录比应有的多。

基本查询是:

SELECT
    a.id                AS parent_id,
    b.id                AS child_one_id,
    c.*
FROM
    parent                          AS a
    LEFT JOIN child_one             AS b ON a.id = b.parent_id
    LEFT JOIN child_two             AS c ON (
        a.id = c.parent_id
        AND c.user_id = '1234'
        AND c.deleted_at IS NULL
    )
WHERE (
    a.user_id = '1234' OR c.parent_id IS NOT NULL
);

即父表保留连接到两个子表,两个子表之间未指定任何关系,并且过滤器仅应用于返回用户拥有记录或用户通过child_two链接到记录的结果。

据我对LEFT JOIN的理解,如果数据库在右侧表中找不到匹配的记录,它将生成一个“空”记录,且所有值都设置为NULL。

但是,在这种情况下,它会生成一些记录,其中“空”记录似乎是通过隐式类型转换完成的。

# parent_id, child_one_id, id, parent_id, created_at, updated_at, deleted_at
     27    ,     29      ,   ,          ,           ,           , 
     27    ,     32      ,  0,         0, 0000-00-00 00:00:00, 0000-00-00 00:00:00, 
     27    ,     47      ,  0,         0, 0000-00-00 00:00:00, 0000-00-00 00:00:00, 
     30    ,     26      ,   ,          ,           ,           , 
     30    ,     46      ,  0,         0, 0000-00-00 00:00:00, 0000-00-00 00:00:00, 

即对于某些记录,它将为child_two生成一个“ NULL”记录,但是对于其他记录,它似乎已经执行了类型转换以为child_two创建一个“归零”记录。

(而且在任何人问之前,不,在child_two中没有任何ID为零的记录!)

我还证明了有两种方法可以阻止生成归零记录:

1)从查询中删除child_one

2)将child_one的联接更改为“ LEFT JOIN child_one AS b ON (a.id = b.parent_id AND b.user_id = '1234')

但是,这不能解释为什么触发这种类型转换,或者为什么只为某些记录触发这种类型转换。遗憾的是,我尽最大努力锻炼自己的Google-fu未能挖掘出任何可能的解释。

因此,尽管我已经有了解决该问题的解决方案,但我还是非常想了解为什么/如何创建“清零”记录-我们在列表中使用“ LEFT JOIN x ... WHERE x.id IS NULL”地方数!

更新: 我设法在某些临时表克隆中重现了该问题,减少了列数,每个表中的记录数也最少。

http://sqlfiddle.com/#!9/faa3d0/1

使用上述SQL,我已经能够在生产服务器上的多个架构上重现该问题。 但是,它不会在我们的测试或开发服务器上发生,也不会在sqlfiddle中发生

所以这似乎是我们生产服务器所特有的。

有趣的一点是,如果我将主索引放在child_two上,则该问题不再发生。尽管解释计划表明查询仍在使用“ job_id”索引来检索数据。

当前,我们正在以下MySQL版本上运行:

  • 生产:5.7.1-4-log(Percona服务器(GPL),版本'4',修订版 '5c940e1')
  • 测试:5.7.21-21(Percona服务器(GPL),版本“ 21”, 修订版'2a37e4e')
  • Dev:5.7.21-21(Percona服务器(GPL),发行版 '21',修订版'2a37e4e')

并且sqlfiddle在MySQL 5.6上运行。

这表明这是Percona 5.7版本中的一个问题,该问题在5.7.11-4版本之后的某个时候得到解决。但是,我在发行说明中看不到任何潜在的候选者。

我们将在不久的将来升级生产服务器,因此希望该问题能够得到解决。同时,如果有人能够识别解决该问题的补丁程序(和/或可以用来缓解该问题的任何配置),将不胜感激!

0 个答案:

没有答案