我們有一個基於id字段(主鍵)從表中刪除一些行的查詢。這是一個非常簡單的查詢:(如70K)提高Sql Delete的性能
delete all from OUR_TABLE where ID in (123, 345, ...)
問題是節數IDS可以是巨大的,所以查詢需要較長的時間。有什麼辦法可以優化嗎? (我們正在使用sybase - 如果這很重要)。
我們有一個基於id字段(主鍵)從表中刪除一些行的查詢。這是一個非常簡單的查詢:(如70K)提高Sql Delete的性能
delete all from OUR_TABLE where ID in (123, 345, ...)
問題是節數IDS可以是巨大的,所以查詢需要較長的時間。有什麼辦法可以優化嗎? (我們正在使用sybase - 如果這很重要)。
請考慮分批運行。一次循環運行1000條記錄可能比一個查詢執行任何操作都快得多,並且此外不會將表格一直鎖定在其他用戶處。
如果您有級聯刪除(以及大量受影響的外鍵表)或觸發器,您可能需要以更小的批次運行。你必須體驗一下,看看哪個是你的情況的最佳數字。我已經有了一些表格,我不得不分批刪除100個表格,其中有50000個工作表格(有幸在這種情況下,我刪除了一百萬條記錄)。
但在任何連我會把我打算刪除到一個臨時表,並從那裏刪除我的鍵值。
我想知道是否解析IN中有70K條目的子句是一個問題。你是否嘗試過使用連接的臨時表?
不知道Sybase,但在SQLServer中,這也是我第一次嘗試優化刪除。 – 2009-02-23 10:58:07
請問our_table有刪除級聯的參考嗎?
有兩種方法可以使像這樣的語句執行:
創建一個新表,並複製所有,但刪除行。之後交換表格(alter table name ...
)我建議嘗試一下,即使聽起來很愚蠢。有些數據庫在複製時比在刪除時快得多。
分區你的表。創建N個表並使用視圖將它們合併成一個表。將行按照刪除標準分組到不同的表中。這個想法是刪除整個表而不是刪除單個行。
+1這是我的建議。 – Elijah 2009-02-23 11:38:14
Sybase可以處理IN子句中的70K個參數嗎?我使用的所有數據庫對於IN
子句的參數數量都有一些限制。例如,Oracle有大約1000個的限制。
您可以創建子選擇而不是IN子句嗎?這將縮短SQL。也許這可能有助於IN子句中的大量值。事情是這樣的:
DELETE FROM OUR_TABLE WHERE ID IN
(SELECT ID FROM somewhere WHERE some_condition)
刪除大量記錄,可以加快與數據庫中的一些干預措施,如果數據庫模型許可證。這裏有一些策略:
你可以通過刪除索引,刪除記錄和重新創建索引來加快速度。這將消除重新平衡索引樹,同時刪除記錄。
禁止觸發器的表,如果您有任何,如果您的業務規則允許的。刪除記錄,然後啓用觸發器。
最後,按照其他建議 - 製作包含不會被刪除的行的表的副本,然後刪除原始,重命名副本並重新創建完整性約束(如果有)。
我會嘗試的1,2和3的組合。如果還是不行,那麼4.如果一切都慢,我會尋找更大的盒子 - 更多的內存,更快的磁盤。
找出什麼是使用了性能!
在很多情況下,你可以使用所提供的解決方案之一。但也可能有其他的(基於Oracle的知識,所以在其他數據庫上會有所不同)編輯:剛剛看到你提到了sybase:
但請記住:找出什麼是性能優先使用。
當您使用DDL語句確保您理解並接受它可能對交易和備份的後果。
嘗試按照與表格相同的順序對要傳入的「ID」進行排序,或者存儲索引。然後,您可以在磁盤緩存中獲得更多匹配。
將要刪除的ID放入臨時表中,該表的Ids按與主表相同的順序排序,可讓數據庫在主表上進行簡單掃描。
您可以嘗試使用多於一個連接,並通過連接吐出工作以便使用數據庫服務器上的所有CPU,但是請考慮先取出哪些鎖等。
我也認爲,臨時表可能是最好的解決方案。
但是,如果您要執行「從...刪除ID(從...中選擇ID)」,那麼對於大型查詢它仍然會很慢。因此,我建議您使用連接刪除 - 許多人不知道該功能。
因此,鑑於此示例表:
-- set up tables for this example
if exists (select id from sysobjects where name = 'OurTable' and type = 'U')
drop table OurTable
go
create table OurTable (ID integer primary key not null)
go
insert into OurTable (ID) values (1)
insert into OurTable (ID) values (2)
insert into OurTable (ID) values (3)
insert into OurTable (ID) values (4)
go
然後,我們可以寫我們的刪除代碼如下:
create table #IDsToDelete (ID integer not null)
go
insert into #IDsToDelete (ID) values (2)
insert into #IDsToDelete (ID) values (3)
go
-- ... etc ...
-- Now do the delete - notice that we aren't using 'from'
-- in the usual place for this delete
delete OurTable from #IDsToDelete
where OurTable.ID = #IDsToDelete.ID
go
drop table #IDsToDelete
go
-- This returns only items 1 and 4
select * from OurTable order by ID
go
這是ASE或ASA?你知道你的版本號嗎? – AdamH 2009-02-24 14:08:02
它是ASE版本10x。 – amit 2009-02-25 03:08:53