Mysql 使用ORDER BY';x';使用联接,但保留不带';t没有'的值;x';

Mysql 使用ORDER BY';x';使用联接,但保留不带';t没有'的值;x';,mysql,optimization,Mysql,Optimization,这是一个相对复杂的问题的简化版本,我和我的同事无法完全理解这个问题 考虑两个表,表a和表b。在我们的CMS中,table_a保存数据库中存储的所有数据的元数据,table_b有一些更具体的信息,因此为了简单起见,一个title和date列 目前,我们的查询如下所示: SELECT * FROM `table_a` LEFT OUTER JOIN `table_b` ON (table_a.id = table_b.id) WHERE table_a.col = 'value' ORDER BY

这是一个相对复杂的问题的简化版本,我和我的同事无法完全理解这个问题

考虑两个表,
表a
表b
。在我们的CMS中,
table_a
保存数据库中存储的所有数据的元数据,
table_b
有一些更具体的信息,因此为了简单起见,一个
title
date

目前,我们的查询如下所示:

SELECT * 
FROM `table_a` LEFT OUTER JOIN `table_b` ON (table_a.id = table_b.id)
WHERE table_a.col = 'value'
ORDER BY table_b.date ASC
LIMIT 0,20
表a
有大量行时,这种情况会严重恶化。如果更改了联接
右外部联接
(这会触发MySQL使用
table_b.date
上设置的索引),则查询速度会无限快,但不会产生相同的结果(因为如果
table_b.date
没有值,则会忽略它)

这在我们的CMS中成为一个问题,因为如果用户在日期列上排序,任何没有设置日期的行都会从界面中消失,从而造成混乱的用户界面体验,并且很难为缺少日期的行添加日期

是否有一种解决方案可以:

  • 使用
    表b
    。日期索引,以便 该查询将更好地扩展
  • 以某种方式保留这些行 没有日期的
    表b
    设置以便用户可以输入 资料

  • 我要谈谈second ArtoAle的评论。由于
    order by
    应用于
    表b
    中缺少行的外部联接中的空值,因此这些行无论如何都会出现顺序错误

    模拟的外部连接是丑陋的部分,所以让我们先看看它。Mysql除了之外没有,因此您需要根据存在编写查询

    SELECT table_a.col1, table_a.col2, table_a.col3, ... NULL as table_b_col1, NULL as ...
    FROM
        table_a
    WHERE
        NOT EXISTS (SELECT 1 FROM table_a INNER JOIN table_b ON table_a.id = table_b.id);
    
    它应该是
    UNION ALL
    ed,并将原始查询作为内部联接。需要使用
    UNION\u ALL
    来保持原始顺序


    无论您做什么,这种查询可能都会非常慢,因为不会有一个索引随时支持“外键不存在”类型的查询。这基本上可以归结为表_a.id中的索引扫描以及表_b.id中对应行的查找(或者并行扫描)

    我要谈谈第二艺术节的评论。由于
    order by
    应用于
    表b
    中缺少行的外部联接中的空值,因此这些行无论如何都会出现顺序错误

    模拟的外部连接是丑陋的部分,所以让我们先看看它。Mysql除了之外没有,因此您需要根据存在编写查询

    SELECT table_a.col1, table_a.col2, table_a.col3, ... NULL as table_b_col1, NULL as ...
    FROM
        table_a
    WHERE
        NOT EXISTS (SELECT 1 FROM table_a INNER JOIN table_b ON table_a.id = table_b.id);
    
    它应该是
    UNION ALL
    ed,并将原始查询作为内部联接。需要使用
    UNION\u ALL
    来保持原始顺序


    无论您做什么,这种查询可能都会非常慢,因为不会有一个索引随时支持“外键不存在”类型的查询。这基本上可以归结为表_a.id中的索引扫描以及表_b.id中对应行的查找(或者并行扫描)

    因此,我们最终实现了一个不同的解决方案,虽然结果不如使用索引,但它仍然提供了大约25%的速度提升

    我们删除联接,而是使用ORDER BY子查询:

    SELECT * 
    FROM `table_a`
    WHERE table_a.col = 'value'
    ORDER BY (
       SELECT date 
       FROM table_b 
       WHERE id = table_a.id
    ) ASC
    LIMIT 0,20
    

    因此,我们最终实现了一个不同的解决方案,虽然结果不如使用索引,但它仍然提供了大约25%的速度提升

    我们删除联接,而是使用ORDER BY子查询:

    SELECT * 
    FROM `table_a`
    WHERE table_a.col = 'value'
    ORDER BY (
       SELECT date 
       FROM table_b 
       WHERE id = table_a.id
    ) ASC
    LIMIT 0,20
    

    你可以做一个正确的连接加上一个联合…你可以做一个正确的连接加上一个联合。。。