2009-07-07 90 views
2

我有一個數據庫基礎架構,我們經常(至少每天一次)將源表的全部內容複製到大約20個目標數據庫。由於使用的複製代碼(我們必須使用常規的oracle查詢,無法控制或直接訪問源數據庫) - 這會導致對源表進行20個全表排序。如何針對重複的全表排序優化oracle查詢?

有什麼辦法可以在查詢中對此進行優化嗎?我正在尋找一些能夠基本告訴甲骨文「我將重複整理這張桌子」的東西? MySQL有一個myisamchk的選項,你可以告訴它對錶進行排序並保持排序順序,但顯然這不適用於多種原因。

目前,還有一些涉及中間表(從A到B,然後從B到C同步)。我們確實可以控制中間表,所以如果有調整選項,那也是有用的。

一般來說,查詢幾乎都是非常簡單的形式:

select a, b, c, d, e, ... z from tbl1 order by a, b, c, d, e, ... z; 

我知道流,但如上所述,主要來源表是我們無法控制的,所以我們贏了」不能在那裏使用流。 (另外,這些源表每天都從快照中完全重建,因此流無法正常工作。)

+0

爲了進一步說明 - 複製代碼正在對源數據庫和目標數據庫進行並行行級比較,並對目標表執行一整套單獨的行更新(I/U/D)它與源同步。同樣的全表選擇和排序也是針對目標表運行的。 – 2009-07-07 23:43:40

+0

我沒有得到你爲什麼要排序,如果目標是從一個表/數據庫複製數據到另一個,你能解釋一下嗎? – 2009-07-08 09:42:54

回答

0

有助於排序問題的一些事情是在排序的列上有索引(和也加入表格,如果他們不在那裏)。您也可以創建已經排序的物化視圖,Oracle會保留緩存的排序結果。

+0

你可以在單個表上做一個聚集索引,這會按排序順序。它有優點和缺點。 Asktom.oracle.tom對此有很好的建議。但我認爲,當你加入一堆表格時,這不會有太大的影響。 – 2009-07-07 23:53:13

+0

索引組織表由主鍵'排序'(或更正確結構化)。在索引集羣中,Oracle數據庫將具有相同集羣鍵值的行存儲在一起。它們不一定以排序順序存儲。也就是說,如果聚集在部門ID上,則DEPT 10中的所有僱員將在一起,並且DEPT 20中的所有僱員一起,但是DEPT 20可以在DEPT 10之前在全表掃描中出來。 – 2009-07-08 00:56:04

0

您不會完全說明覆制是如何完成的或涉及的數據量(或您爲什麼要對數據進行排序)。

如果目標是儘量減少對源數據庫的影響,那麼最好的方法可能是提取到中間文件並將文件加載到目標數據庫中。可以在中間文件(如果是純文本)上完成排序,或者作爲導出或導入目標數據庫的一部分。

In source database : 
create table export_emp_info 
organization external 
(type oracle_datapump 
    default directory DATA_PUMP_DIR 
    location ('emp.dmp') 
) as select emp_id, emp_name, dept_id from emp order by dept_id 
/


Copy file then, import in dest database: 
create table import_emp_info 
(EMP_ID     NUMBER(12), 
EMP_NAME     VARCHAR2(100), 
DEPT_ID     NUMBER) 
organization external 
(type oracle_datapump 
    default directory DATA_PUMP_DIR 
    location ('emp.dmp') 
) 
/
insert into emp_info select * from import_emp_info; 

如果你不想或者不能對源數據庫外部表,您可以使用表emp的直EXPDP(可能使用NETWORK_LINK如果你有到源數據庫目錄中的機會有限結構)和QUERY進行排序。

2

你可以看看multi-table INSERT功能。它應該執行一次全面掃描並將插入到多個表中。考慮(10gR2):

SQL> CREATE TABLE t1 (ID NUMBER); 

Table created 
SQL> CREATE TABLE t2 (ID NUMBER); 

Table created 

SQL> INSERT ALL 
    2  INTO t1 VALUES (d_id) 
    3  INTO t2 VALUES (d_id) 
    4 /* your select goes here */ 
    5 SELECT ROWNUM d_id FROM dual d CONNECT BY LEVEL <= 5; 

10 rows inserted 
SQL> SELECT COUNT(*) FROM t1; 

    COUNT(*) 
---------- 
     5 
SQL> SELECT COUNT(*) FROM t2; 

    COUNT(*) 
---------- 
     5 

您將不得不檢查它是否適用於數據庫鏈接。

0

您可以將數據從源表A加載到中間表B,然後在B和目標表C之間進行分區交換。完全複製,不涉及排序。

0

這種I/U/D形式的複製是MERGE命令的作用。非常值得懷疑的是,需要昂貴的排序合併,而我期望看到散列連接。只要散列表可以存儲在內存中,散列連接幾乎不會比掃描表更昂貴。

便利的優化是基於非關鍵屬性存儲散列值,以便您可以在關鍵列上的源表和目標表之間進行連接,並比較小散列值而不是整列列 - 改變檢測變得容易。