【问题标题】:how to prove 2 sql statements are equivalent如何证明2条sql语句是等价的
【发布时间】:2011-06-19 14:17:44
【问题描述】:

我开始用连接和子语句重写一个复杂的 SQL 语句,并获得了一个看起来更简单的语句。我通过在相同的数据集上运行并获得相同的结果集来测试它。一般来说,我如何(从概念上)证明这两个语句在任何给定的数据集中都是相同的?

【问题讨论】:

  • 正式?通过使用关系代数:en.wikipedia.org/wiki/Relational_algebra
  • 您是担心性能,还是只担心数据的正确性?不同的查询可能由数据库引擎以不同的方式处理。尽管它们在形式上可能是等价的,但实际上它们可能非常不同。 Oracle 的解释计划之类的内容可能有助于了解数据库实际上 对您的 sql 执行的操作。如果两者都做同样的事情,你赢了;-D
  • 正式证明对我来说可能太多了。我只是想确保它们是等效且正确的,而不必在所有数据集上运行它们。
  • 您可以将这两个查询插入解析器 (antlr.org/grammar/list) 以获得它们等效的解析树。如果你对这两棵树进行归一化,你也许可以用这种方式证明它们是等价的。
  • @Martin 在此处发布两个查询的问题,添加赏金 - 利润!

标签: sql theory performance


【解决方案1】:

我建议学习关系代数(正如 Mchl 指出的那样)。如果您想认真优化查询和正确设计数据库,这是您需要的最基本概念。

但是,如果您有足够的数据进行测试,我会建议一种丑陋的蛮力方法来帮助您确保正确的结果:创建两个版本的视图(以便更易于管理比较)并比较结果。我的意思是像

create view original as select xxx yyy zzz;
create view new as select xxx yyy zzz;
-- If the amount differs something is quite obviously very wrong
select count(*) from original;
select count(*) from new;
-- What is missing from the new one?
select *
from original o
where not exists (
 select * 
 from new n
 where o.col1=n.col2 and o.col2=n.col2 --and so on
);
-- Did something extra appear?
select *
from new o
where not exists (
 select *
 from old n
 where o.col1=n.col2 and o.col2=n.col2 --and so on
)

正如 cmets 中的其他人所指出的,您可以将这两个查询都提供给您正在使用的产品的优化器。大多数时候你会得到一些可以用人类来解析的东西,完整的执行路径图以及子查询对性能的影响等等。它通常是用类似的东西来完成的

explain plan for 
select * 
from ...
where ...
etc

【讨论】:

  • 相同的输出不需要查询等价,但不同的输出证明查询不等价。
猜你喜欢
  • 2013-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-17
  • 2014-06-01
  • 1970-01-01
相关资源
最近更新 更多