【问题标题】:query limit constraint propagation into subquery查询限制约束传播到子查询
【发布时间】:2023-03-16 00:42:01
【问题描述】:

这是我的简化情况

create table t1 (i integer, d text);
insert into t1 values (0,'aa0');
insert into t1 values (1,'aa1');
insert into t1 values (2,'aa2');
insert into t1 values (3,'aa3');
insert into t1 values (4,'aa4');
insert into t1 values (5,'aa5');
insert into t1 values (6,'aa6');
insert into t1 values (7,'aa7');
insert into t1 values (8,'aa8');
insert into t1 values (9,'aa9');

create table t2 (i integer, e text);
insert into t2 values (0,'aa0');
insert into t2 values (1,'ba1');
insert into t2 values (2,'aa2');
insert into t2 values (3,'ba3');
insert into t2 values (4,'aa4');
insert into t2 values (5,'ba5');
insert into t2 values (6,'aa6');
insert into t2 values (7,'ba7');
insert into t2 values (8,'aa8');
insert into t2 values (9,'ba9');

然后我有一个外部 SELECT,其目的是打印出表 t1 以获取 ID (i) 的选择列表

select d from t1 where i in (3,4) limit 4;
d
----
aa3
aa4

ID 集已生成,因此我可以得到

select d from t1 where i in (3,4,1,6,7) limit 4;
d
----
aa1
aa3
aa4
aa6

有时 ID 集是这样的内部 SELECT 子查询的结果

select d from t1 where i in (select i from t2 where e>'b') limit 4;
d
----
aa1
aa3
aa5
aa7

在我的真实案例中,t1 和 t2 很大,内部 SELECT 可以生成一个大 ID 列表,外部选择将使用其限制约束进行核对。

我的问题是,查询优化器是否检测到这个外部限制约束并将其传播到内部选择中?

如果答案是否定的,那么我应该加倍努力,我的查询生成器必须像这样在内部 SELECT 中显式移动限制约束

select d from t1 where i in (select i from t2 where e>'b' limit 4);
d
----
aa1
aa3
aa5
aa7

在询问之前,我查看了 EXPLAIN 和 EXPLAIN QUERY PLAN,但这超出了我的知识范围,无法从那里回答。

【问题讨论】:

    标签: sqlite query-optimization subquery-factoring


    【解决方案1】:

    SQLite 没有optimization 可以将 LIMIT 子句移动到子查询中,子查询展平不适用于 IN 子句。

    这由 EXPLAIN 确认(地址 22 在外循环中):

    sqlite>解释select d from t1 where i in(select i from t2 where e>'b')限制4; addr 操作码 p1 p2 p3 p4 p5 注释 ---- ------------- ---- ---- ---- ------------- -- ------ -------- 0 初始化 0 26 0 00 从 26 开始 1 整数 4 1 0 00 r[1]=4;限制计数器 2 OpenRead 0 2 0 2 00 根=2 iDb=0; t1 3 倒带 0 24 0 00 4 Noop 0 0 0 00 开始 IN expr 5 一次 0 16 0 00 6 OpenEphemeral 3 1 0 k(1,B) 00 nColumn=1 7 OpenRead 1 3 0 2 00 根=3 iDb=0; t2 8 倒带 1 15 0 00 9 列 1 1 2 00 r[2]=t2.e 10 Le 3 14 2 (BINARY) 52 如果 r[3]

    请注意,没有 ORDER BY 子句的 LIMIT 可能不是很有用,除非您实际上想要随机的行样本。

    【讨论】:

    • 感谢 CL 的及时回复。然后我会处理 LIMIT 位置。在我的情况下,限制只是验证查询的一种方式。顺序不相关,内部选择中选择的 ID 是正则表达式匹配,然后列表是匹配列表。它有点像“grep foo bifgile | head -4”。我还不流利的解释,也没有发现测试,因为我的真实案例非常大并且有很多测试。
    • 我应该在我的小测试中使用 EXPLAIN ,对此感到抱歉。
    • 您并没有真正理解 EXPLAIN 输出……
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    相关资源
    最近更新 更多