0

我有一个查找表 ( ##lookup)。我知道这是一个糟糕的设计,因为我在复制数据,但它极大地加快了我的查询速度。我有一个填充此表的查询

insert into ##lookup select distinct col1,col2,... from table1...join...etc...

我想模拟这种行为:

delete from ##lookup
insert into ##lookup select distinct col1,col2,... from table1...join...etc...

这将清楚地正确更新表。但这是很多插入和删除。它弄乱了我的索引并锁定了表格以供选择。

该表也可以通过以下方式更新:

delete from ##lookup where not in (select distinct col1,col2,... from table1...join...etc...)
insert into ##lookup (select distinct col1,col2,... from table1...join...etc...) except if it is already in the table

第二种方式可能需要更长的时间,但我可以说“没有锁”,我将能够从表中进行选择。

关于如何以第二种方式编写查询的任何想法?

4

2 回答 2

2
DELETE LU
FROM ##lookup LU
LEFT OUTER JOIN Table1 T1 ON T1.my_pk = LU.my_pk
WHERE T1.my_pk IS NULL

INSERT INTO ##lookup (my_pk, col1, col2...)
SELECT T1.my_pk, T1.col1, T1.col2...
FROM Table1 T1
LEFT OUTER JOIN ##lookup LU ON LU.my_pk = T1.my_pk
WHERE LU.my_pk IS NULL

您还可以使用 WHERE NOT EXISTS 而不是上面的 LEFT JOIN 来查找不存在的行。

如果您使用的是 SQL 2008,您可能还想查看 MERGE 语句。否则,您不会保持表同步 - 您只是保持 PK 同步。如果一个表中的一列发生变化,而另一列则不会在上面反映出来。

无论哪种方式,听起来您可能需要考虑优化查询。虽然复制数据似乎可以很好地解决您的性能问题,但您可以看到它可能会带来很多麻烦(这只是其中之一)。你最好找到性能不佳的根本原因并修复它,而不是穿上这个丑陋的创可贴。

于 2010-06-15T17:46:42.650 回答
0

如果您计划对整个表进行核攻击,则会记录所有 DELETE,这会降低性能。根据您要处理的行数,您可能只使用未记录的 TRUNCATE。

您的 SELECT 语句需要多长时间?如果选择需要少量时间并且您不经常运行它,您可以尝试这样的事情。

select distinct ... INTO #tempTable1 from table1...join...etc...

begin transaction drop table ##lookup select * into ##lookup from #tempTable1 commit transaction

汤姆的回答可能是最有力的,但我只是想我会加入一些替代方案。不知道为什么与真实表相比需要全局临时表???

于 2010-06-19T23:48:14.570 回答