2014-07-16 144 views
1

我有一个表ACCPLAN(PRIMARY KEY:ACCOUNT_ID)的Oracle SQL:联盟和加盟

ACCOUNT_ID     PLAN_TYPE   OTHER_STUFF 

ACC1      PLAN_TYPE_ONE  .... 
ACC2      PLAN_TYPE_TWO  .... 
ACC3      PLAN_TYPE_ONE  .... 
ACC4      PLAN_TYPE_TWO  ... 

我还有一个表ACCTRANSACTION(PRIMARY KEY - >(ACCOUNT_ID,TRANSACTION_ID)

ACCOUNT_ID TRANSACTION_ID TRANSACTION_AMOUNT TXN_TYPE 

ACC1  1    100    TXN_TYPE_1 
ACC1  2    300    TXN_TYPE_2 
ACC2  1    400    TXN_TYPE_2 
ACC3  1    400    TXN_TYPE_3 

有5个固定的plan_types和20个固定的txn_type。对于每个plan_type,只有少数几个事务处理类型是 (例如:TXN_TYPE_1和TXN_TYPE_2可能用于 PLAN_TYPE_ONE和TXN_TYPE_2和TXN_TYPE_3可能用于PLAN_TYPE_TWO)

我正在尝试从ACCTRANSACTION从ACCPLAN

交易信息及其他
细节这可以通过2种方式

方法1

检索每个plan_type做,做一个工会

select ap.account_id,ap.other_stuff,at.transaction_amount 
from accplan ap, acctransaction at 
where ap.account_id = at.account_id 
and ap.plan_type = PLAN_TYPE_ONE 
and at.txn_type in (TXN_TYPE_1,TXN_TYPE_2); 

union 

select ap.account_id,ap.other_stuff,at.transaction_amount 
from accplan ap, acctransaction at 
where ap.account_id = at.account_id 
and ap.plan_type = PLAN_TYPE_TWO 
and at.txn_type in (TXN_TYPE_2,TXN_TYPE_3); 

union 

... 

APPROACH 2

检索使用一个查询所有plan_types

select ap.account_id,ap.other_stuff,at.transaction_amount 
    from accplan ap, acctransaction at 
    where ap.account_id = at.account_id 
    and 
    ((ap.plan_type = PLAN_TYPE_ONE and at.txn_type in (TXN_TYPE_1,TXN_TYPE_2)) 

    or 

    (ap.plan_type = PLAN_TYPE_TWO and at.txn_type in (TXN_TYPE_2,TXN_TYPE_3)); 

哪种方法更好地考虑两个表具有庞大的数据?请建议。

+0

我投票结束,因为你的问题是基于意见,这在SO这里是题外话。您应该在两个查询上运行解释纯文本,并查看哪一个最适合您的数据库。 –

+0

我明白,在这种情况下“最好”只意味着最快。这可以在知道的数据库(Oracle)中进行测量和再现。 即使很多事情都会影响结果(索引,统计数据,版本,配置选项,硬件),但理解数据库的执行计划可以让您更好地了解什么可以更快。 无论如何,定期会有很多与性能相关的问题,可能会被重定向到某个stackexchange站点。 Meta中有什么关于这个的吗? – borjab

+0

与你的问题无关:你应该停止在where子句中使用过时和老式的隐式连接,并使用明确的JOIN运算符(在from子句中)。我也同意第二个可能更有效率。如果你确实想要第一个,那么你应该使用'UNION ALL'来代替删除重复的开销。 –

回答

2

使用连接。工会要求对整个结果进行排序,这对您的数据库来说是一项昂贵的操作。

此外。最好一次阅读表格,并对每个记录进行一些复杂的检查,而不是多次阅读,以便进行较小的检查。

声明:我可以想象一些非常奇怪的情况,如果数据库查询规划器决定大条件不够有选择性并且不使用索引,并且每个较小的条件都使用它,则第一个查询运行得更快。行数越多,我会使用第二个选项越多。

+0

+1好的解释和免责声明。值得注意的是,Oracle确实有一些与'UNION'有关的不同转换,但是它们都不适用于此。例如,[USE_CONCAT](http://docs.oracle.com/cd/E11882_01/server.112/e41084/sql_elements006。htm#BABIAFIB)提示将'OR'转换为'UNION ALL',并且[join factorization](https://blogs.oracle.com/optimizer/entry/optimizer_transformations_join_factorization)可以防止重新读取'UNION ALL'中的大表。奇怪的是,连接因子分解仅适用于*更复杂的场景,并不能帮助解决这些简单的问题。 –

+0

那么,当你使用'UNION ALL'而不是'UNION'时,你可以避免排序。 –

+1

UNION ALL更快。如果他不介意重复或者如果他确定没有可能出现重复的情况,他可以使用它们。 即使有联盟,我也会用你刚才说的显式连接运算符来连接JOIN。 – borjab