Если я остановлю длительный запрос, он откатится? - PullRequest
25 голосов
/ 02 октября 2008

Запрос, который используется для циклического перебора 17 миллионов записей для удаления дубликатов выполняется уже около 16 часов , и я хотел знать, остановлен ли запрос прямо сейчас, если он завершит удаление операторов или, если он был удален во время выполнения этого запроса? Действительно, если я остановлю это, он завершит удаление или откатит?

Я обнаружил, что когда я делаю

 select count(*) from myTable

То, что строки, которые он возвращает (при выполнении этого запроса), примерно на 5 меньше, чем было количество начальных строк. Очевидно, что ресурсы сервера крайне скудны, значит ли это, что этот процесс занял 16 часов, чтобы найти 5 дубликатов (когда их на самом деле тысячи), и это могло бы продолжаться несколько дней?

Этот запрос занял 6 секунд для 2000 строк тестовых данных, и он отлично работает с этим набором данных, поэтому я решил, что для полного набора потребуется 15 часов.

Есть идеи?

Ниже приведен запрос:

--Declare the looping variable
DECLARE @LoopVar char(10)


    DECLARE
     --Set private variables that will be used throughout
      @long DECIMAL,
      @lat DECIMAL,
      @phoneNumber char(10),
      @businessname varchar(64),
      @winner char(10)

    SET @LoopVar = (SELECT MIN(RecordID) FROM MyTable)

    WHILE @LoopVar is not null
    BEGIN

      --initialize the private variables (essentially this is a .ctor)
      SELECT 
        @long = null,
        @lat = null,
        @businessname = null,
        @phoneNumber = null,
        @winner = null

      -- load data from the row declared when setting @LoopVar  
      SELECT
        @long = longitude,
        @lat = latitude,
        @businessname = BusinessName,
        @phoneNumber = Phone
      FROM MyTable
      WHERE RecordID = @LoopVar

      --find the winning row with that data. The winning row means 
      SELECT top 1 @Winner = RecordID
      FROM MyTable
      WHERE @long = longitude
        AND @lat = latitude
        AND @businessname = BusinessName
        AND @phoneNumber = Phone
      ORDER BY
        CASE WHEN webAddress is not null THEN 1 ELSE 2 END,
        CASE WHEN caption1 is not null THEN 1 ELSE 2 END,
        CASE WHEN caption2 is not null THEN 1 ELSE 2 END,
        RecordID

      --delete any losers.
      DELETE FROM MyTable
      WHERE @long = longitude
        AND @lat = latitude
        AND @businessname = BusinessName
        AND @phoneNumber = Phone
        AND @winner != RecordID

      -- prep the next loop value to go ahead and perform the next duplicate query.
      SET @LoopVar = (SELECT MIN(RecordID) 
    FROM MyTable
    WHERE @LoopVar < RecordID)
    END

Ответы [ 12 ]

0 голосов
/ 02 октября 2008

В качестве цикла ваш запрос будет плохо масштабироваться даже при наличии соответствующих индексов. Запрос должен быть переписан в одно утверждение, как указано в вашем предыдущем вопросе .

Если вы не запускаете его явно в транзакции, он только откатит выполняющуюся инструкцию.

0 голосов
/ 02 октября 2008

Я почти уверен, что это отрицательно. Иначе какой будет точка транзакции?

...