查询引擎如何评估此SQL查询?

时间:2009-05-22 19:33:53

标签: sql sql-execution-plan

我正在玩SQL查询,我想起了这个问题 - select x,y from table T

这里x和y可以是像2.0 / 5.0 OR 1 + 2这样的算术表达式,结果具有表T的行数,第一列的值为2.0 / 5.0,即0.444444,第二列的值为3。

我很想知道这个查询是如何执行的。我已经了解到,在SQL查询引擎中,存在从查询的SQL表示到内部表示(如关系代数)的映射,然后对其进行优化以生成最佳查询执行计划。

如果错误,请更正我的理解 - 对于我所说的查询,我的查询Q内部映射会与select * from table T的内部表示相同。然后对于返回的所有行,n个列被投射出来,其中n是Q中所述的算术表达式的数量.n列的所有行都将对算术表达式进行各自的评估。

欢呼声

6 个答案:

答案 0 :(得分:1)

很可能取决于数据库。

如果你用于x和y的表达式是常数,那么一个像样的数据库应该识别它并且只执行一次计算并将值放在结果集中。

如果表达式包含其他一些函数,那么每次函数都有副作用时都必须执行表达式。

一般来说,你是正确的,计算from子句中描述的虚拟表,然后我相信应用where子句中的过滤器,然后是select子句。

答案 1 :(得分:1)

不,表达式只评估一次(至少在MS SQL Server中)。

如果你这样做,你可以很容易地看到:

select rand() from tableT

所有行都具有相同的随机数。

答案 2 :(得分:1)

它会扫描,因为没有where子句。这是sql server的设置showplan_all

select 2.0/5.0,1+2 from YourTable                                                            
  |--Compute Scalar(DEFINE:([Expr1003]=(0.400000), [Expr1004]=(3)))                           
       |--Index Scan(OBJECT:([wppusdev].[dbo].[AP_Voucher].[YourTable_Index]))

答案 3 :(得分:0)

从MS SQL的角度来看......

它可能不会像SELECT * FROM Table那样进行评估,因为引擎应该意识到它实际上并不需要表中的任何列,所以它很可能会选择表上最薄的索引并扫描它。

实际的方程式只应评估一次,然后用作常数。

答案 4 :(得分:0)

PostgreSQL将首先评估表达式,然后很可能在表上执行顺序扫描。此外,正如其他地方所述,许多SQL版本都有一个EXPLAIN关键字,它将告诉您如何在给定当前实现的情况下评估特定查询。

答案 5 :(得分:0)

数据库是否为每行评估一次函数是一个实现决策。在Oracle中,您可以从表中选择dbms_random.random(),并为每一行返回不同的数字。例如,如果要以随机顺序返回行,这将非常有用。