繁体   English   中英

sql where子句中的列顺序

[英]column order in sql where clause

所有

  1. sql where子句中的列顺序是否有效? 我在网上搜索,然后发现一些建议,首先要说的是联接,然后是其他过滤器。 例如,

     select t1.a, t2.b from table1 t1, table2 t2 where t1.a = t2.a and t1 > 1 and t2 > 2; 

我将t1 > 1更改为t1.a = t2.a的前面是否有任何疑问?

  1. 我想知道存在子句中的列顺序。 例如,

     select t1.a, t2.b from table1, table2 t2 where t1.a = t2.a and not exists (select 1 from table3 t3 where t1.a = t3.a and t1.b = t3.b) 

如果将t1.b = t3.b更改为t1.b = t3.b ,是否有任何效果,我会t3.b = t1.b吗? 列顺序至关重要吗?

  1. 谁能解释sql select execute步骤,并提供一些有用的教程链接?

要摆脱这种情况,请改用显式的ANSI SQL-92语法,并使用JOIN关键字:

select t1.a, t2.b 
from table1 t1
inner join table2 t2 on t1.a = t2.a
where  t1 > 1 and t2 > 2;

这样,您将不再在WHERE子句中具有连接条件,并且可以轻松添加更多条件。

对于第二个查询,您可以为此使用OUTER JOIN

select t1.a, t2.b 
from table1
inner join table2 t2 on t1.a = t2.a
LEFT JOIN table3 t3 on t1.a = t3.a and t1.b = t3.b
where t3.a IS NULL;

我知道这不能回答您的问题,但是这种旧的连接语法是where子句中所有条件都含糊不清的问题。 不建议这样做,因此请避免使用:

人们通常说WHERE子句中的谓词顺序不影响性能是正确 但是,仍然存在这样的情况,即我们经常对系统中的数据(尤其是其分布和偏斜)了解更多,而优化器无法从其统计信息中得出这些信息。 在这种情况下,对我们来说,向优化器提供最好的信息是很重要的。

这是从我上周遇到的真实情况中摘录的一个示例(我现在没有时间运行测试用例,但稍后再进行)。

情况:三张桌子,一个父母和两个孩子。 任务是通过在其子级中查找非唯一行来选择父级中的唯一行。 所有表都有数百万行。

我的第一次尝试是这样的:

select parent.*
from   child1
       , child2
       , parent
where child1.col_a = 'whatever'
and child2.col_n = 9999
and child1.parent_id = child2.parent_id
and parent.id = child2.parent_id

该查询重新设置了正确的结果集,但性能却很差。 解释计划表明查询已脱离CHILD2。 这是错误的,因为CHILD1上的过滤器更具选择性。 所以我重新编写了这样的查询:

select parent.*
from   child1
       , child2
       , parent
where child1.col_a = 'whatever'
and child2.col_n = 9999
and child2.parent_id = child1.parent_id
and parent.id = child1.parent_id

现在,查询启动了CHILD1,性能提高了一个数量级以上。 那不会一直发生,但是我说摆弄WHERE子句仍然是一种有效的调优技术。

CBO是一款非常智能的软件。 但是,我们不能只是在上面抛出一个杂乱无章的WHERE子句,并期望它每次都能产生最佳的解释计划。 查询越复杂(其中复杂度由联接数定义),以有意义的方式组织WHERE子句就越重要。 它没有任何危害,而且可能会有所帮助。


顺便说一句,那些说ANSI连接语法不会再次影响性能的人在大多数时候都是正确 有时,它的确会导致优化程序制定出次等的执行计划。 了解更多

基于成本的优化器(CBO)下where子句中谓词的顺序并不重要,因为CBO会在合适的情况下高兴地重新排列谓词(除非您在其中暗示了告诉oracle不要这样做的提示)这个)。

对于基于规则的优化器来说,确实应该注意谓词的顺序,但是希望您所使用的Oracle版本不是很老,仍然使用RBO。

where子句中的顺序并不重要。 ANSI JOIN语法提高了可读性,但不影响性能。 为了证明这一点:

create table t1 (a number, x number);
create table t2 (a number, b number);
insert into t1 (a, x) select level, mod(level,100) from dual connect by level <= 100000;
insert into t2 (a, b) select level, mod(level,10)  from dual connect by level <= 100000;
exec dbms_stats.gather_table_stats(user,'t1');
exec dbms_stats.gather_table_stats(user,'t2');
set autotrace trace explain

所有四个查询

select t1.a, t2.b from t1, t2 where t1.a=t2.b and t1.x > 5 and t2.b > 5;
select t1.a, t2.b from t1, t2 where t1.a=t2.b and t2.b > 5 and t1.x > 5;
select t1.a, t2.b from t1, t2 where t1.x > 5 and t2.b > 5 and t1.a=t2.b;
select t1.a, t2.b from t1 join t2 on t1.a=t2.b where t1.x > 5 and t2.b > 5;

产生完全相同的查询计划

Plan hash value: 282751716
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      | 44444 |   434K|    88   (7)| 00:00:02 |
|*  1 |  HASH JOIN         |      | 44444 |   434K|    88   (7)| 00:00:02 |
|*  2 |   TABLE ACCESS FULL| T2   | 44444 |   130K|    42   (5)| 00:00:01 |
|*  3 |   TABLE ACCESS FULL| T1   | 94946 |   649K|    44   (5)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("T1"."A"="T2"."B")
   2 - filter("T2"."B">5)
   3 - filter("T1"."X">5 AND "T1"."A">5)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM