SQL 优化器/执行计划 - 重复子查询
Posted
技术标签:
【中文标题】SQL 优化器/执行计划 - 重复子查询【英文标题】:SQL Optimizer / Execution Plan - Repeated Subqueries 【发布时间】:2013-03-25 15:03:59 【问题描述】:注意:我目前正在一个 sqlite3 数据库上运行我的查询,但欢迎来自任何其他 DBMS 专业知识的回答......
我想知道查询优化器是否会尝试识别重复的查询/子查询,如果是,则只运行一次。
这是我的示例查询:
SELECT *
FROM table1 AS t1
WHERE t1.fk_id =
(
SELECT t2.fk_id
FROM table2 AS t2
WHERE t2.id = 1111
)
OR t1.fk_id =
(
SELECT local_id
FROM ID_MAP
WHERE remote_id =
(
SELECT t2.fk_id
FROM table2 AS t2
WHERE t2.id = 1111
)
);
将嵌套查询
SELECT t2.fk_id
FROM table2 AS t2
WHERE t2.id = 1111
只运行一次(并缓存其结果以供进一步访问)?
在这个例子中没什么大不了的,因为它是一个只执行两次的简单查询,但是我需要它运行 在我的实际程序中(它抓取所有子记录(表 1) 关联到由外键绑定的父记录 (table2)。它还检查一个 id 映射表以确保它查询 对于本地生成的 id 以及真实/更新/新密钥)。
非常感谢您对此提供的任何帮助,谢谢。
【问题讨论】:
【参考方案1】:SQLite 有一个非常简单的查询优化器,甚至不会尝试检测相同的子查询:
> create table t(x);
> explain query plan
select * from t
where x in (select x from t) or
x in (select x from t);
0|0|0|SCAN TABLE t (~500000 rows)
0|0|0|EXECUTE LIST SUBQUERY 1
1|0|0|SCAN TABLE t (~1000000 rows)
0|0|0|EXECUTE LIST SUBQUERY 2
2|0|0|SCAN TABLE t (~1000000 rows)
这同样适用于 CTE 和视图;如果性能确实很重要,最好的办法是为子查询的结果创建一个临时表。
【讨论】:
"explain query plan" 我什至不知道 DBMS 有这样的命令,太棒了。我遇到的问题的核心是将本地生成的临时 ID 与更新到远程数据库后发回的“真实”临时 ID 同步。它的父/子外键关系变得棘手。父记录和子记录都可以在本地生成,从而获得临时 ID,并且我使用 ID_MAP 表进行跟踪。我试图避免应用程序级锁定,但我不确定最好的选择是使用事务(开始/提交)还是嵌套查询来击败潜在的竞争条件? 为了防止竞争,使用事务。 (如果没有显式事务,每个命令将被包装到一个自动事务中,因此围绕多个命令的显式事务甚至可以减少事务开销。)但是,应用程序级锁可能比SQLite's locking scheme 更有效。无论如何,在遇到实际性能问题之前不要费心优化。 好的。嵌套查询是自动触发的,还是被分解成单独的语句(反过来又被包装成单独的事务)?我问 b/c 我不确定天气是否暗示嵌套查询不会自动触发(因此防止比赛)?感谢所有的帮助。 ... 另外,我正在远离应用程序级锁 b/c 涉及两个独立的进程,它们通过一个作为表实现的请求队列进行通信。我开始编写锁代码,意识到我刚刚在锁表上遇到了竞争条件,在前进程和后台进程之间,所以决定解决它所在的问题(此外,锁检查开始到处弹出) .我仍然希望我可以使用它们。 自动事务处理整个语句(包括任何子查询,以及在触发器中完成的任何事情)。【参考方案2】:当您要求其他数据库提供见解时......
在 Oracle DBMS 中,任何独立的子查询都只会执行一次。
SELECT t2.fk_id
FROM table2 AS t2
WHERE t2.id = 1111 -- The result will be the same for any row in t1.
当然,依赖子查询需要重复执行。
依赖子查询示例:
SELECT t2.fk_id
FROM table2 AS t2
WHERE t2.id = t1.t2_id -- t1.t2_id will have different values for different rows in t1.
【讨论】:
有趣的概念,独立/独立的子查询。完全有道理,只是在写这个问题时我没有意识到。谢谢!以上是关于SQL 优化器/执行计划 - 重复子查询的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server查询优化器执行计划“语句提前终止的原因:超时”