2009-07-07 91 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命令的作用。非常值得怀疑的是,需要昂贵的排序合并,而我期望看到散列连接。只要散列表可以存储在内存中,散列连接几乎不会比扫描表更昂贵。

便利的优化是基于非关键属性存储散列值,以便您可以在关键列上的源表和目标表之间进行连接,并比较小散列值而不是整列列 - 改变检测变得容易。