Обновление 500 000 строк в SQL Server с уникальными данными - PullRequest
2 голосов
/ 04 ноября 2011

Итак, я работаю над «де-идентификацией» базы данных, где по существу меняется каждый фрагмент информации. В большинстве небольших таблиц простое обновление не потребовало слишком много времени (до таблиц с 10 000 строк или около того. Теперь я перешел к таблице с примерно 500 000 строк.

Я читал, что самый быстрый способ сделать такое "обновление" - это просто выбрать во временной таблице обновление нужного столбца. (Я читаю это здесь. Самый быстрый способ обновить 120 миллионов записей )

Проблема с этим заключается в том, что OP обновляет все подобные значения одним значением, где каждое из моих значений различно, т.е. он обновляет нулевые строки в одном столбце до -1, я обновляю каждый столбец в мой новый ряд более или менее случайной даты; Это то, что у меня так далеко.

--The only Index on Treatments is a Clustered Primary Key (TreatmentID)
SELECT * INTO #Treatments_temp
FROM Treatments
CREATE CLUSTERED INDEX IDX_Treatments ON #Treatments_temp(TreatmentID)

SET @rows = (SELECT TOP 1 TreatmentID
             FROM Treatments
             ORDER BY TreatmentID Desc)

WHILE (@rows > 0)
  BEGIN

    --There are only 500,000 records in this table from count(*) but the PK is much 
    --higher (some records are deleted, made in error ETC so this if statement is my
    --attempt to bypass the code for @rows that don't actually exist.

    IF (SELECT TreatmentID FROM #Treatments_temp WHERE TreatmentID = @rows) IS NOT NULL
      BEGIN
      DECLARE @year INT;
      DECLARE @month INT;
      DECLARE @date INT;
      DECLARE @newStartDate SMALLDATETIME;
      DECLARE @multiplier FLOAT;

      SET @multiplier = (SELECT RAND());

      SET @year = @multiplier * 99 + 1900;
      SET @month = @multiplier * 11 + 1;
      SET @date = @multiplier * 27 + 1;

      SET @newStartDate = DATEADD(MONTH,((@year-1900)*12)+@month-1,@date-1);

      UPDATE #Treatments_temp
      SET StartDate = @newStartDate
      WHERE TreatmentID = @rows

      UPDATE #Treatments_temp
      SET EndDate = DATEADD(MINUTE, @timebetween, @newStartDate)
      WHERE TreatmentID = @rows
      END

  SET @rows = @rows - 1
  END

Ответы [ 3 ]

2 голосов
/ 04 ноября 2011

Не зная больше о том, что у вас есть, я думаю, было бы проще всего:

  • Поместите свою «рандомизирующую» логику в скалярную функцию
  • Создайте узкую таблицу, указав ID и результат функции для каждого ID
  • Обновите таблицу Treatment, указав INNER JOIN в узкой таблице, чтобы получить новое значение

Нет необходимости в построчном подходе к этому.

1 голос
/ 09 декабря 2011

Я думаю, что это должно сработать:

-- using NewID() instead of Rand() because Rand() is only interpreted once for the entre query while NewID() is for each record
-- Based on your logic I understand newStartDate had to be between 1 jan 1801 and 28 dec 1999 
DECLARE @multiplier float
DECLARE @max_int    float
DECLARE @daterange  float

SELECT @max_int   = Power(Convert(float, 2), 31), -- signed int !
       @daterange = DateDiff(day, '1 jan 1801', '28 dec 1999')

UPDATE Treatments
   SET @multiplier  = (@max_int - Convert(real, ABS(BINARY_CHECKSUM(NewID())))) / @max_int, -- returns something between 0 and 1
       StartDate    = DateAdd(day, Convert(int, (@daterange * @multiplier)), '1 jan 1801') -- returns somewhere in the daterange

-- test 'spread'
SELECT COUNT(*), COUNT(DISTINCT StartDate), Min(StartDate), Max(StartDate) FROM Treatments

Если кто-то захочет проверить это, вы можете использовать это для генерации некоторых тестовых данных (@Kulingar: убедитесь, что не уронили вашу таблицу случайно =)

IF DB_ID('test') IS NULL CREATE DATABASE test
GO
USE test
GO
IF Object_ID('test..Treatments') IS NOT NULL DROP TABLE test..Treatments
GO
SELECT row_id = IDENTITY(int, 1, 1), StartDate = CURRENT_TIMESTAMP INTO Treatments FROM sys.columns, sys.objects
0 голосов
/ 04 ноября 2011

я бы выполнил это написание небольшой программы, которая бы:

  1. выбрала * и поместила в структуру
  2. изменила данные в структуре
  3. заменила старуюданные с новыми данными (возможно удаление таблицы + создание таблицы или усечения + вставка в)

таким образом вы выполняете свою логику за пределами базы данных и ограничивает необработанное значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...