获得两个几乎相同的表之间的记录差异

时间:2009-10-05 18:36:32

标签: sql performance not-exists

我有一个流程将40多个结构相同的数据库整合到一个统一数据库中,唯一的区别是统一数据库将project_id字段添加到每个表中。

为了尽可能高效,我尝试只将记录从源数据库复制/更新到统一数据库(如果已添加/更改)。我从统一数据库中删除过时的记录,然后复制到任何不存在的记录中。要删除过期/已更改的记录,我正在使用类似于此的查询:

DELETE FROM <table> 
 WHERE NOT EXISTS (SELECT <primary keys> 
                     FROM <source> b 
                    WHERE ((<b.fields = a.fields>) or 
                          (b.fields is null and a.fields is null))) 
  AND PROJECT_ID = <project_id>

这大部分都有效,但源数据库中的一个表有超过700,000条记录,此查询需要一个多小时才能完成。

如何提高此查询效率?

4 个答案:

答案 0 :(得分:2)

使用时间戳或更好的审计表来识别自“X”时间以来发生更改的记录,然后在上次同步开始时保存时间“X”。我们将它用于界面提要。

答案 1 :(得分:0)

您可能想尝试使用NULL过滤器进行LEFT JOIN:

DELETE      <table> 
FROM        <table> t
LEFT JOIN   <source> b 
        ON (t.Field1 = b.Field1 OR (t.Field1 IS NULL AND b.Field1 IS NULL))
        AND(t.Field2 = b.Field2 OR (t.Field2 IS NULL AND b.Field2 IS NULL))
        --//...
WHERE       t.PROJECT_ID = <project_id>
        AND b.PrimaryKey IS NULL --// any of the PK fields will do, but I really hope you do not use composite PKs

但如果您要比较所有非PK列,那么您的查询将受到影响。

在这种情况下,最好在两个数据库上添加UpdatedAt TIMESTAMP字段(如DVK建议的那样),您可以使用AFTER UPDATE触发器更新,然后您的同步过程会更快,因为您创建了包含PK的索引和UpdatedAt列。

答案 2 :(得分:0)

您可以重新排序WHERE语句;它有四个比较,最有可能首先失败。

如果您可以稍微更改数据库/应用程序,并且您需要再次执行此操作,则显示“已更新”的位字段可能不是一个糟糕的添加。

答案 3 :(得分:0)

我通常会重写这样的查询以避免不... Not In虽然表现糟糕,但Not Exists在此方面有所提升。

查看此文章http://www.sql-server-pro.com/sql-where-clause-optimization.html

我的建议......

将pkey列选择到工作/临时表中,添加一个列(标志)int default 0 not null,并索引pkey列。如果子查询中存在记录,则标记标记= 1(更快!)。 将主查询中的子选择替换为exists where(从temptable中选择pkey,其中flag = 0)

这样做可以创建一个“不存在”值列表,这些值可以包含在一个全包集合中。

这是我们的总集。 {1,2,3,4,5}

这是现有的一套 {1,3,4}

我们从这两组创建工作表(技术上是左外连接) (记录:存在)

{1:1,2:0,3:1,4:1,5:0}

我们的'不存在的记录'

{2,5}(选择* from flag = 0)

我们的产品......更快(索引!)

{2,5} = {2,5}

中的{p> {1,2,3,4,5}

{1,2,3,4,5}不在{1,3,4} = {2,5}

这可以在没有工作台的情况下完成,但是它的使用使得可以更容易地看到发生的事情。

克里斯