我有一個SQL Server數據庫,其中存儲了數百萬條記錄。現在,我要不斷地刪除記錄的一個大數目,所以我做的是相同的執行中運行數千個查詢是這樣的:一次執行數千個SQLServer查詢
delete TWEET
from TWEET
where REQUEST_ID >= x and TWEET_ID = y and ID < z
單查詢是直接的,但把它們放在一起是極其緩慢。
你會對我建議什麼?
我有一個SQL Server數據庫,其中存儲了數百萬條記錄。現在,我要不斷地刪除記錄的一個大數目,所以我做的是相同的執行中運行數千個查詢是這樣的:一次執行數千個SQLServer查詢
delete TWEET
from TWEET
where REQUEST_ID >= x and TWEET_ID = y and ID < z
單查詢是直接的,但把它們放在一起是極其緩慢。
你會對我建議什麼?
您可以使用它。每回合可以刪除100000行。這比在同一時間刪除所有行的速度更快。
DECLARE @RC INT = 1
WHILE @RC > 0
BEGIN
delete TOP(100000)
from TWEET
where REQUEST_ID >= x and TWEET_ID = y and ID < z
SET @RC = @@ROWCOUNT
END
使用JOINed表可能是你最好的選擇(見下文)。另一個選擇是使用Service Broker:向SB發送刪除請求,並且有一個異步進程在有CPU時刪除它。
------------------------------------------------------------------------
-- Create a table to hold the delete requests:
CREATE TABLE DeleteTweets (
ID INT IDENTITY(1,1) PRIMARY KEY
, REQUEST_ID INT
, TWEET_ID INT
)
GO
------------------------------------------------------------------------
-- Create an index to keep the deletions fast:
CREATE INDEX IX_DeleteTweets ON dbo.DeleteTweets (REQUEST_ID, TWEET_ID)
GO
------------------------------------------------------------------------
-- However you can put your delete requests into that table. This might
-- be part of you front-end application or via some batch process:
INSERT INTO dbo.DeleteTweets
(REQUEST_ID, TWEET_ID)
VALUES (0, /*REQUEST_ID*/, 0 /*TWEET_ID*/)
, (0, /*REQUEST_ID*/, 0 /*TWEET_ID*/)
, (0, /*REQUEST_ID*/, 0 /*TWEET_ID*/)
, (0, /*REQUEST_ID*/, 0 /*TWEET_ID*/)
, (0, /*REQUEST_ID*/, 0 /*TWEET_ID*/)
GO
------------------------------------------------------------------------
-- Delete from the main table via JOIN:
DELETE t
FROM TWEET t
INNER JOIN dbo.DeleteTweets dt
ON t.REQUEST_ID = dt.REQUEST_ID
AND t.TWEET_ID = dt.TWEET_ID
GO
------------------------------------------------------------------------
-- Once they're done, empty the table so you can re-fill with new deletion requests:
TRUNCATE TABLE dbo.DeleteTweets
GO
--in查詢窗口1
DROP TABLE TWEETDEL
GO
DROP TABLE TWEET
GO
CREATE TABLE TWEET
(ID int NOT NULL
,REQUEST_ID AS ID*2
,TWEET_ID AS ID*10
)
GO
INSERT TWEET WITH (TABLOCKX) (ID)
SELECT TOP 20000000 id
FROM
(SELECT ROW_NUMBER() OVER (ORDER BY a.id) AS id
FROM sys.sysobjects AS a, sys.syscolumns AS b, sys.syscolumns AS c) x
GO
ALTER TABLE TWEET ADD PRIMARY KEY (ID)
GO
SELECT IDENTITY(INT,1,1) AS TWEETDELPK, *
INTO TWEETDEL
FROM TWEET
WHERE REQUEST_ID%14=0
GO
ALTER TABLE TWEETDEL ADD PRIMARY KEY (TWEETDELPK)
GO
ALTER TABLE TWEETDEL
ADD CONSTRAINT fk101
FOREIGN KEY (ID) REFERENCES TWEET(ID) ON DELETE CASCADE
GO
- 在同一窗口
SET NOCOUNT OFF
DECLARE @ID INT
CR:
DELETE TOP (SELECT CNT FROM ##) t WITH (PAGLOCK)
FROM TWEET AS t
WHERE EXISTS
(SELECT 1 FROM TWEET AS x WHERE T.ID = X.ID)
IF @@ROWCOUNT >0 GOTO CR
- 在另一個窗口
CREATE TABLE ## (CNT INT)
INSERT ## SELECT 1000
select COUNT(1) from tweetdel
select COUNT(1) from tweet
檢查LOCKING - IF鎖定保持開放時間過長,升高或降低尺寸按照
UPDATE ## SET CNT =5000
SELECT resource_type, resource_associated_entity_id,
request_status, request_mode,request_session_id,
resource_description
FROM sys.dm_tran_locks
WHERE resource_database_id = DB_ID()
AND request_mode in ('x')
你能想出一個更廣泛處理這些情況的查詢嗎? – tadman
要麼'和id([你的ID以逗號分隔])'或者把你所有的ID放在一張表中,並且'從ID上的連接表中刪除' – Kritner
你的事務日誌看起來如何? –