Удаление данных из большой таблицы - PullRequest
5 голосов
/ 13 мая 2009

У меня есть таблица с 10 полями для хранения информации GPS для клиентов. Со временем, когда мы добавили больше клиентов, эта таблица выросла до 14 миллионов строк. По мере поступления данных gps служба постоянно вставляет строку в таблицу. 90% данных не являются откровенными, т. Е. Клиенту все равно, где автомобиль находился 3 месяца назад, но самые последние данные используются для создания отчетов об отслеживании. Моя цель - написать sql для очистки данных старше месяца.

Вот моя проблема, я не могу использовать TRUNCATE TABLE, так как я бы все потерял? Вчера я написал оператор удаления таблицы с предложением where. Когда я запустил его в тестовой системе, он заблокировал мою таблицу, и симуляторы gps периодически терпели неудачу. Кроме того, мой журнал транзакций вырос до 6 ГБ, поскольку он пытался регистрировать каждое удаление.

Моей первой мыслью было постепенное удаление данных, начиная с самого старого, но мне было интересно, есть ли лучший способ.

Ответы [ 15 ]

0 голосов
/ 19 мая 2009

Я придумал следующий скрипт T-SQL, который получает произвольное количество последних данных.

IF EXISTS(SELECT name FROM sys.tables WHERE name = 'tmp_xxx_tblGPSVehicleInfoLog')
BEGIN
    PRINT 'Dropping temp table tmp_xxx_tblGPSVehicleInfoLog'
    DROP TABLE tmp_xxx_tblGPSVehicleInfoLog
END
GO

PRINT 'Creating temp table tmp_xxx_tblGPSVehicleInfoLog'
CREATE TABLE [dbo].[tmp_xxx_tblGPSVehicleInfoLog](
    [GPSVehicleInfoLogId] [uniqueidentifier] NOT NULL,
    [GPSVehicleInfoId] [uniqueidentifier] NULL,
    [Longitude] [float] NULL,
    [Latitude] [float] NULL,
    [GroundSpeed] [float] NULL,
    [Altitude] [float] NULL,
    [Heading] [float] NULL,
    [GPSDeviceTimeStamp] [datetime] NULL,
    [Milliseconds] [float] NULL,
    [DistanceNext] [float] NULL,
    [UpdateDate] [datetime] NULL,
    [Stopped] [nvarchar](1) NULL,
    [StopTime] [datetime] NULL,
    [StartTime] [datetime] NULL,
    [TimeStopped] [nvarchar](100) NULL
) ON [PRIMARY]
GO

PRINT 'Inserting data from tblGPSVehicleInfoLog to tmp_xxx_tblGPSVehicleInfoLog'
SELECT * INTO tmp_xxx_tblGPSVehicleInfoLog 
FROM tblGPSVehicleInfoLog 
WHERE tblGPSVehicleInfoLog.UpdateDate between '03/30/2009 23:59:59' and '05/19/2009  00:00:00'
GO

PRINT 'Truncating table tblGPSVehicleInfoLog'
TRUNCATE TABLE tblGPSVehicleInfoLog
GO

PRINT 'Inserting data from tmp_xxx_tblGPSVehicleInfoLog to tblGPSVehicleInfoLog'
INSERT INTO tblGPSVehicleInfoLog 
SELECT * FROM tmp_xxx_tblGPSVehicleInfoLog 
GO
0 голосов
/ 14 мая 2009

Производительность довольно быстрая при падении стола, даже очень большого. Вот что я хотел бы сделать. Сценарий вашей таблицы в комплекте с индексами из Management Studio. Отредактируйте скрипт и запустите его, чтобы создать копию таблицы. Назовите это table2. Выберите вставку, чтобы сохранить данные, которые вы хотите сохранить в новой таблице2. Переименуйте старую таблицу, скажем, tableOld. Переименуйте table2 с оригинальным именем. Подождите. Если никто не кричит на тебя, брось table2. Есть некоторый риск. 1) Проверьте, есть ли триггеры или ограничения, определенные в исходной таблице. Они не могут быть включены в сценарий, созданный студией управления. 2) если в исходной таблице есть поля идентификаторов, вам, возможно, придется включить identity_insert перед вставкой в ​​новую таблицу.

0 голосов
/ 13 мая 2009

Использует ли оператор delete какие-либо индексы в таблице? Часто огромное улучшение производительности может быть достигнуто либо путем изменения оператора для использования существующего индекса, либо для добавления индекса в таблицу, который помогает повысить производительность запроса, выполняемого оператором удаления.

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

0 голосов
/ 13 мая 2009

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

Это простой шаг - он не забивает ваши журналы повторов и т. Д.

Есть базовое вступление ко всему этому здесь

0 голосов
/ 13 мая 2009

Имейте в виду, что большинство баз данных блокируют соседние записи в индексе во время транзакции, поэтому полезно будет сократить ваши операции. Я предполагаю, что ваши вставки завершаются неудачно по истечении времени ожидания блокировки, поэтому удаляйте ваши данные небольшими пакетными транзакциями. Я бы предложил однопоточный сценарий Perl, который проходит через самые старые 1000 фрагментов. Я надеюсь, что ваш первичный ключ (и, надеюсь, кластеризованный индекс в том случае, если они каким-то образом оказались двумя разными вещами) может быть соотнесен со временем, так как это было бы лучшим способом удалить.

PseudoSQL: Выберите максимум (primId) <3_months_ago Удалить из таблицы, где primId <maxPrimId limit 1000 </p>

Теперь вот действительно забавная часть: все эти удаления МОГУТ привести к беспорядку в ваших индексах и потребовать их перестройки, чтобы машина не работала медленно. В этом случае вам придется либо заменить современного раба, либо просто потерпеть некоторое время простоя. Убедитесь, что вы тестировали этот возможный случай на своем тестовом компьютере.

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