0

我有一个将 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

4 回答 4

2

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

于 2009-10-05T18:45:15.557 回答
0

我通常会重写这样的查询来避免 not... Not In 对性能来说很糟糕,尽管 Not Exists 对此有所改进。

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

我的建议...

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

这样做的结果是能够创建一个“不存在”值的列表,这些值可以从一个全包集合中包含在内地使用。

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

这是现有的集合 {1,3,4}

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

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

我们的一组“不存在的记录”

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

我们的产品......而且速度更快(索引!)

{2,5} 中的 {1,2,3,4,5} = {2,5}

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

这可以在没有工作台的情况下完成,但它的使用使得可视化正在发生的事情变得更容易。

克里斯

于 2009-10-05T19:27:20.523 回答
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 列的索引.

于 2009-10-05T19:00:25.870 回答
0

您可以重新排序 WHERE 语句;它有四个比较,把最有可能失败的一个放在第一位。

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

于 2009-10-05T19:08:32.547 回答