2017-10-17 125 views
2

我有一個SQL Server數據庫,其中存儲了數百萬條記錄。現在,我要不斷地刪除記錄的一個大數目,所以我做的是相同的執行中運行數千個查詢是這樣的:一次執行數千個SQLServer查詢

delete TWEET 
from TWEET 
where REQUEST_ID >= x and TWEET_ID = y and ID < z 

單查詢是直接的,但把它們放在一起是極其緩慢。

你會對我建議什麼?

+1

你能想出一個更廣泛處理這些情況的查詢嗎? – tadman

+0

要麼'和id([你的ID以逗號分隔])'或者把你所有的ID放在一張表中,並且'從ID上的連接表中刪除' – Kritner

+1

你的事務日誌看起來如何? –

回答

3

您可以使用它。每回合可以刪除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 
+0

我應該多次運行一次還是一次性運行? – sirdan

+0

只執行一次。我們有一個while循環,它迭代刪除直到完成記錄。 –

+0

我必須從Java運行這個,所以y和z對於我在Java中使用的while循環的每一輪都會有所不同。它是否會陷入循環與您的解決方案,還是它與多個不同的參數工作? – sirdan

0

使用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 
+0

不知道爲什麼刪除使用聯接TWEET和DeletedTweets之間有什麼區別,請您澄清一下。順便說一句,創建/更新索引也很耗時。而且,將行插入到DeleteTweets中需要時間。 – FLICKER

+0

我已經嘗試了一個INNER JOIN,但它的工作情況比我的查詢還要糟糕。 @FLICKER我在問題的下面添加了一條評論,我在這裏解釋了原因 – sirdan

0

--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')