我有一张cats
有 42,795,120 行的表。
显然这是很多行。所以当我这样做时:
/* owner_cats is a many-to-many join table */
DELETE FROM cats
WHERE cats.id_cat IN (
SELECT owner_cats.id_cat FROM owner_cats
WHERE owner_cats.id_owner = 1)
查询超时:(
(编辑:我需要增加我的 CommandTimeout
值,默认只有 30 秒)
我不能使用TRUNCATE TABLE cats
,因为我不想从其他主人那里吹走猫。
我正在使用 SQL Server 2005,并将“恢复模型”设置为“简单”。
所以,我想过做这样的事情(顺便说一句,从应用程序执行这个 SQL):
DELETE TOP (25) PERCENT FROM cats
WHERE cats.id_cat IN (
SELECT owner_cats.id_cat FROM owner_cats
WHERE owner_cats.id_owner = 1)
DELETE TOP(50) PERCENT FROM cats
WHERE cats.id_cat IN (
SELECT owner_cats.id_cat FROM owner_cats
WHERE owner_cats.id_owner = 1)
DELETE FROM cats
WHERE cats.id_cat IN (
SELECT owner_cats.id_cat FROM owner_cats
WHERE owner_cats.id_owner = 1)
我的问题是:我可以DELETE
在 SQL Server 2005 中的行数阈值是多少?
或者,如果我的方法不是最优的,请提出更好的方法。谢谢。
这篇文章对我的帮助不够:
编辑(2010 年 8 月 6 日):
好的,我在再次阅读上面的链接后才意识到我在这些表上没有索引。此外,你们中的一些人已经在下面的评论中指出了这个问题。请记住,这是一个虚构的模式,所以甚至id_cat
不是 PK,因为在我的现实生活模式中,它不是一个独特的领域。
我将索引放在:
cats.id_cat
owner_cats.id_cat
owner_cats.id_owner
我想我还在掌握这个数据仓库的窍门,显然我需要所有JOIN
字段的索引,对吧?
但是,我需要几个小时才能完成这个批量加载过程。我已经在这样做了SqlBulkCopy
(以块的形式,而不是一次全部 4200 万)。我有一些索引和 PK。我阅读了以下帖子,这些帖子证实了我的理论,即即使是批量复制,索引也会减慢速度:
所以我会DROP
在复制之前访问我的索引,然后CREATE
在完成后重新搜索它们。
由于加载时间长,我需要一段时间来测试这些建议。我会报告结果。
更新(2010 年 8 月 7 日):
汤姆建议:
DELETE
FROM cats c
WHERE EXISTS (SELECT 1
FROM owner_cats o
WHERE o.id_cat = c.id_cat
AND o.id_owner = 1)
仍然没有索引,对于 4200 万行,它需要 13:21 分:秒,而上述方式需要 22:08。然而,对于 1300 万行,他用了 2:13 而不是我的老方法 2:10。这是一个好主意,但我仍然需要使用索引!
更新(2010 年 8 月 8 日):
有什么大错特错!现在打开索引,我上面的第一个删除查询花费了 1:9 hrs:min (是的一个小时!)与 22:08 min:sec 和 13:21 min:sec 相比 2:10 min:sec 用于 42 百万行和分别为 13 百万行。我现在要尝试使用索引进行 Tom 的查询,但这是朝着错误的方向发展。请帮忙。
更新(2010 年 8 月 9 日):
Tom 的删除需要 1:06 小时:分钟(42 百万行)和 10:50 分钟:秒(13 百万行),而索引分别为 13:21 分钟:秒和 2:13 分钟:秒。 当我使用一个数量级的索引时,删除在我的数据库上花费的时间更长! 我想我知道为什么,我的数据库 .mdf 和 .ldf 在第一次(4200 万)删除期间从 3.5 GB 增长到 40.6 GB! 我究竟做错了什么?
更新(2010 年 8 月 10 日):
由于缺乏任何其他选择,我想出了一个我觉得乏善可陈的解决方案(希望是暂时的):
- 将数据库连接超时时间增加到 1 小时(
CommandTimeout=60000;
默认为 30 秒) - 使用 Tom 的查询:
DELETE FROM WHERE EXISTS (SELECT 1 ...)
因为它执行得快一点 DROP
运行删除语句之前的所有索引和 PK (???)- 运行
DELETE
语句 CREATE
所有索引和 PK
似乎很疯狂,但至少它比TRUNCATE
从 first 开始使用和重新开始我的负载要快owner_id
,因为我的一个owner_id
需要 2:30 hrs:min 来加载,而我刚刚描述的删除过程需要 17:22 min:sec 42 百万行。(注意:如果我的加载过程抛出异常,我会重新开始owner_id
,但我不想吹走之前的owner_id
,所以我不想上桌,这就是我尝试使用的原因。)TRUNCATE
owner_cats
DELETE
任何帮助仍将不胜感激:)