簡體   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