嘟嘟程序猿

15.查询优化和子查询 半查询(gold_axe)

2019-08-09  本文已影响20人  胖达_4b7e

一些重写规则

唯一索引的等值查询,被任务查询的时间少到可忽略,


这里table1就是常量表, 假设 table1.primary_key = 1 这行是 1,a语句就会被优化为SELECT * FROM 1,a INNER JOIN table2 ON a= table2.column2

子查询

类型按结果分:

按与外层关系分:

相关查询
这里,子查询里面的条件的n1t1的表, 子查询用到外面表的列
子查询结果集的布尔表达式

IN子查询优化

SELECT * FROM s1 WHERE key1 IN (SELECT common_field FROM s2 WHERE key3 = 'a');

物化表

SELECT * FROM s1 WHERE key1
SELECT common_field FROM s2 WHERE key3 = 'a'
这2个查的是 s1 s2 2张表, 不相关的查询
内层查询的结果集太多, 可能内存发不下,而且 in(这里面太多) 效率太低,
所以, 内层查询的结果会被放到临时表里面, 这个过程会去重(瘦身), 这个过程叫物化

semi-join 半连接

SELECT s1.* FROM s1 SEMI JOIN s2 ON s1.key1 = s2.common_field WHERE key3 = 'a';
这个语句不能执行只做示意
半连接:只关心在s2表中是否存在与之匹配的记录是否存在,而不关心具体有多少条记录与之匹配

执行半连接如何消除重复值:

in 子查询 转成 EXISTS

SELECT
    *
FROM
    s1
WHERE
    key1 IN (
        SELECT
            key3
        FROM
            s2
        WHERE
            s1.common_field = s2.common_field
    )
OR key2 > 1000;
SELECT
    *
FROM
    s1
WHERE
    EXISTS (
        SELECT
            1
        FROM
            s2
        WHERE
            s1.common_field = s2.common_field
        AND s2.key3 = s1.key1// 可以用到s2.key3上的索引了
    )
OR key2 > 1000;

如果IN子查询不满足转换为semi-join的条件,又不能转换为物化表或者转换为物化表的成本太大,那么它就会被转换为EXISTS查询。

派生表消除

SELECT
    *
FROM
    (SELECT * FROM s1 WHERE key1 = 'a') AS derived_s1// 派生表
INNER JOIN s2 ON derived_s1.key1 = s2.key1
WHERE
    s2.key2 = 1;
SELECT
    *
FROM
    s1
INNER JOIN s2 ON s1.key1 = s2.key1
WHERE
    s1.key1 = 'a'
AND s2.key2 = 1;
上一篇 下一篇

猜你喜欢

热点阅读