2017-02-01 15 views
0

テーブルXとトランザクションがあるとします(CUSTOMER_IDは主キーです)。一意のキーによる複数の内部自己結合の最適化

また、この表のクエリのテキストX(機械学習の点で)の「機能」もあります。

クエリ1:

SELECT 
X.CUSTOMER_ID, 
WHEN(X.GENDER = "F" AND X.IS_PREGNANT = TRUE) THEN 1 OTHERWISE 0 AS WILL_BUY_FOR_KIDS 
FROM X 

クエリXXX:

SELECT 
X.CUSTOMER_ID, 
WHEN(X.GENDER = "M" AND X.AVG_AMOUNT > 1000) THEN 1 OTHERWISE 0 AS RICH_DUDE 
FROM X 


タスクがXから算出した全ての "機能" を使用してテーブルを生成することである すべてのこれらのクエリは次のようにしています表。 したがって、 "機能"クエリのテキストを使用して(プログラムで)出力クエリのテキストを作成する必要があります。 のような何か:内部サブクエリの何百もの自己結合時には、上記

SELECT 
* 
FROM SOME_QUERY_1 
INNER JOIN SOME_QUERY_X 
ON SOME_QUERY_1.CUSTOMER_ID = SOME_QUERY_X.CUSTOMER_ID 
... 

このような出力クエリが非常に遅くなることがあります。 SQLエンジンは(回避が参加する)のようなものに、このクエリを "書き換え" になる場合は明らかに、それはクールになる:

SELECT 
CUSTOMER_ID, 
WHEN(X.GENDER = "F" AND X.IS_PREGNANT = TRUE) THEN 1 OTHERWISE 0 AS WILL_BUY_FOR_KIDS, 
WHEN(X.GENDER = "M" AND X.AVG_AMOUNT > 1000) THEN 1 OTHERWISE 0 AS RICH_DUDE, 
..... 
FROM X 


いくつかの質問:

  1. を任意のSQLエンジンがあります上記の最適化を行うことができます(MySQL、PostgreSQLなど)?
  2. 一般的な数値代数では、式を簡略化するための規則が実証されています(例:(a + b) * a = a^2 + b*a)。リレーショナル・アレグレブのルールはありますか?
+0

これらのサブクエリの目的は何ですか? – wildplasser

+0

BTW:postgresはサブクエリを崩壊させるほどスマートですが、x1。*とx2。*は同じタプルを参照していることを検出しません。結果は、2つの索引スキャンのマージ結合です。 – wildplasser

+0

@wildplasser質問に文脈を追加するための説明を更新しました –

答えて

1

オラクルのオプティマイザが作業を行っているようです。

drop table x; 
create table x (a int primary key,b int); 

select x0.b,x1.b,x2.b,x3.b,x4.b,x5.b,x6.b,x7.b,x8.b,x9.b 

from   (select x.a,x.b from x) x0 
     join (select x.a,x.b from x) x1 on x1.a = x0.a 
     join (select x.a,x.b from x) x2 on x2.a = x0.a 
     join (select x.a,x.b from x) x3 on x3.a = x0.a 
     join (select x.a,x.b from x) x4 on x4.a = x0.a 
     join (select x.a,x.b from x) x5 on x5.a = x0.a 
     join (select x.a,x.b from x) x6 on x6.a = x0.a 
     join (select x.a,x.b from x) x7 on x7.a = x0.a 
     join (select x.a,x.b from x) x8 on x8.a = x0.a 
     join (select x.a,x.b from x) x9 on x9.a = x0.a 
;   

は、実行計画に9 ELIMINATE_JOINに注意してください。

--------------------------------------------------------------------------  
| Id | Operation   | Name | Rows | Bytes | Cost (%CPU)| Time  |  
--------------------------------------------------------------------------  
| 0 | SELECT STATEMENT |  |  1 | 26 |  2 (0)| 00:00:01 |  
| 1 | TABLE ACCESS FULL| X |  1 | 26 |  2 (0)| 00:00:01 |  
--------------------------------------------------------------------------  

Query Block Name/Object Alias (identified by operation id):     
-------------------------------------------------------------     

PLAN_TABLE_OUTPUT                
-------------------------------------------------------------------------------- 

    1 - SEL$44564B95/[email protected]$2             

Outline Data                  
-------------                 

    /*+                   
     BEGIN_OUTLINE_DATA               
     FULL(@"SEL$44564B95" "X"@"SEL$2")           
     OUTLINE(@"SEL$3")               
     OUTLINE(@"SEL$2")               
     OUTLINE(@"SEL$1")               
     MERGE(@"SEL$3")               
     MERGE(@"SEL$2")               
     OUTLINE(@"SEL$5428C7F1")             
     OUTLINE(@"SEL$5")               
     OUTLINE(@"SEL$4")               
     MERGE(@"SEL$5428C7F1")              
     MERGE(@"SEL$5")               
     OUTLINE(@"SEL$730B2DEF")             
     OUTLINE(@"SEL$7")               
     OUTLINE(@"SEL$6")               
     MERGE(@"SEL$730B2DEF")              
     MERGE(@"SEL$7")               
     OUTLINE(@"SEL$DE510E9C")             
     OUTLINE(@"SEL$9")               
     OUTLINE(@"SEL$8")               
     MERGE(@"SEL$DE510E9C")              
     MERGE(@"SEL$9")               
     OUTLINE(@"SEL$6C54F645")             
     OUTLINE(@"SEL$11")               
     OUTLINE(@"SEL$10")               
     MERGE(@"SEL$6C54F645")              
     MERGE(@"SEL$11")               
     OUTLINE(@"SEL$5E3B1022")             
     OUTLINE(@"SEL$13")               
     OUTLINE(@"SEL$12")               
     MERGE(@"SEL$5E3B1022")              
     MERGE(@"SEL$13")               
     OUTLINE(@"SEL$D60B40D8")             
     OUTLINE(@"SEL$15")               
     OUTLINE(@"SEL$14")               
     MERGE(@"SEL$D60B40D8")              
     MERGE(@"SEL$15")               
     OUTLINE(@"SEL$B8655000")             
     OUTLINE(@"SEL$17")               
     OUTLINE(@"SEL$16")               
     MERGE(@"SEL$B8655000")              
     MERGE(@"SEL$17")               
     OUTLINE(@"SEL$EC740ABE")             
     OUTLINE(@"SEL$19")               
     OUTLINE(@"SEL$18")               
     MERGE(@"SEL$EC740ABE")              
     MERGE(@"SEL$19")               
     OUTLINE(@"SEL$7AC5A3AA")             
     OUTLINE(@"SEL$20")               
     MERGE(@"SEL$7AC5A3AA")              
     OUTLINE(@"SEL$F6D45FB3")             
     ELIMINATE_JOIN(@"SEL$F6D45FB3" "X"@"SEL$17")        
     ELIMINATE_JOIN(@"SEL$F6D45FB3" "X"@"SEL$15")        
     ELIMINATE_JOIN(@"SEL$F6D45FB3" "X"@"SEL$13")        
     ELIMINATE_JOIN(@"SEL$F6D45FB3" "X"@"SEL$11")        
     ELIMINATE_JOIN(@"SEL$F6D45FB3" "X"@"SEL$9")        
     ELIMINATE_JOIN(@"SEL$F6D45FB3" "X"@"SEL$7")        
     ELIMINATE_JOIN(@"SEL$F6D45FB3" "X"@"SEL$5")        
     ELIMINATE_JOIN(@"SEL$F6D45FB3" "X"@"SEL$3")   
     OUTLINE(@"SEL$5A225B26")             
     ELIMINATE_JOIN(@"SEL$5A225B26" "X"@"SEL$19")        
     OUTLINE_LEAF(@"SEL$44564B95")            
     ALL_ROWS                 
     DB_VERSION('11.2.0.2')              
     OPTIMIZER_FEATURES_ENABLE('11.2.0.2')          
     IGNORE_OPTIM_EMBEDDED_HINTS            
     END_OUTLINE_DATA               
    */                    

Column Projection Information (identified by operation id):      

    1 - "X"."B"[NUMBER,22]              

Note                    
-----                   
    - dynamic sampling used for this statement (level=2)       
+0

クールです。 最も興味深いのは、ELIMINATE_JOINステージは他のSQLエンジンと共通ですか?そのトリックを行うことができる実績のあるリレーショナルルールはありますか、それとも「ハック」ですか? –

+0

こんにちはLars :-)これらの質問はあまりにも広範です。各特定のプロバイダの実装と理論の間には長い距離があります。 –

0

まず、あなたのようにクエリを記述する必要があります

SELECT X1.A * 2, // Some operation on X1.A 
     X2.B/2 // Some operation on X2.B 
FROM X X1 JOIN 
    X X2 
    ON X1.C = X2.C; 

サブクエリは値を提供しない(しかし、私は後でそれに戻ります)。

Cunique(またはprimary key)と宣言されている場合は、フィールドにインデックスがあります。私は、すべてのデータベースがまだJOINを行いますかなり確信しているが、それは本当に速いようになります。

  • プロセスレコード(X1)とレコードへのインデックス
  • リターンでC
  • 検索Cを見つけますすでにメモリに入ってX2になる。

インデックスを通過するための追加のオーバーヘッドは、最初にデータを読み取る場合に比べて大きな負担はありません。

あなたが書いたように、ほとんどのデータベースはこの最適化を実行するのに十分なほどスマートです。サブクエリは無視されます。 MySQLは例外です。サブクエリは実際には実体化されているため、作成したバージョンは哀れなほど遅くなる可能性があります。マテリアライゼーションはインデックスも使用できなくなります。ただし、再書き込みは問題ありません。

データベースに最適化がない理由を尋ねることがあります。データベース開発者は、記述が不適切なものを最適化するよりも、よく記述されたクエリを最適化することに重点を置いています。 JOINが必要ない場合は、クエリの書き込みに注意する必要があります。 (実際には、JOINには1つの用途があり、NULLの値を除外します)。

+0

主な問題は、主キーによる複数の内部自己結合を避けることです。 質問に文脈を追加するために説明を更新しました。 –

+0

確信しないでください... –

関連する問題