Является ли удаление всех записей в таблице плохой практикой в ​​SQL Server? - PullRequest
6 голосов
/ 19 мая 2009

Я перемещаю систему из приложения VB / Access на сервер SQL. Одна общая вещь в базе данных доступа - это использование таблиц для хранения вычисляемых данных, а затем использование этих данных для отчета.
например.

delete from treporttable
insert into treporttable (.... this thing and that thing)
Update treportable set x = x * price where (...etc)  

, а затем отчет запускается из таблицы треппорта

Я слышал, что SQL-серверу не нравится, когда удаляются все записи из таблицы, поскольку он создает огромные журналы и т. Д. Я пробовал таблицы временного sql, но они не сохраняются достаточно долго для отчета, который находится в другом процессе бежать и отчитываться от.

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

Может кто-нибудь сказать мне, есть ли лучший способ для этого, или если моя информация о журналах неверна, и этот код будет хорошо в SQL-сервере.

Ответы [ 9 ]

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

Если вам не нужно регистрировать операцию удаления, вы можете использовать команду truncate table.

Из книг онлайн:

TRUNCATE TABLE функционально идентичен инструкции DELETE без Предложение WHERE: оба удаляют все строки в стол. Но TRUNCATE TABLE - это быстрее и использует меньше системы и ресурсы журнала транзакций, чем DELETE.

http://msdn.microsoft.com/en-us/library/aa260621(SQL.80).aspx

5 голосов
/ 19 мая 2009
delete from sometable

Позволит вам отменить изменения. Поэтому, если ваша таблица очень большая, это может привести к значительному использованию памяти и времени.

Однако, если вы не боитесь неудачи, то:

truncate sometable

Будет работать почти мгновенно и с минимальными требованиями к памяти. Откатов нет.

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

Вы также можете УДАЛИТЬ таблицу и воссоздать ее ... если нет связей.

Оператор [DROP table] безопасен с точки зрения транзакций, а [TRUNCATE] - нет.

Так что от вашей схемы зависит, в каком направлении вы хотите идти !!

Кроме того, используйте SQL Profiler для анализа времени выполнения. Проверьте это и посмотрите, что лучше !!

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

Натану Фегеру:

Вы можете откатить от TRUNCATE. Убедитесь сами:

CREATE TABLE dbo.Test (i INT); ИДТИ INSERT dbo.Test (i) SELECT 1; ИДТИ НАЧАТЬ ТРАНС TRUNCATE TABLE dbo.Test; ВЫБЕРИТЕ Я ОТ dbo.Test; ROLLBACK ИДТИ ВЫБЕРИТЕ Я ОТ dbo.Test; GO

я

(затронуто 0 строк)

я

1

(затронут 1 ряд)

1 голос
/ 19 мая 2009

Рассмотрите возможность использования временных таблиц. Их имена начинаются с #, и они удаляются, когда никто не обращается к ним. Пример:

create table #myreport (
    id identity,
    col1,
    ...
)

Временные таблицы создаются для того, чтобы их выбрасывать, и это происходит очень эффективно.

Другой вариант - использовать TRUNCATE TABLE вместо DELETE. Усечение не будет увеличивать файл журнала.

1 голос
/ 19 мая 2009

Ответ зависит от модели восстановления вашей базы данных. Если вы находитесь в режиме полного восстановления, у вас есть журналы транзакций, которые могут стать очень большими при удалении большого количества данных. Однако, если вы регулярно создаете резервные копии журналов транзакций, чтобы освободить место, это может вас не беспокоить.

Вообще говоря, если регистрация транзакций не имеет для вас никакого значения, вам следует вместо этого TRUNCATE таблицы. Будьте внимательны к любым ключевым семенам, потому что TRUNCATE повторно заполнит таблицу.

РЕДАКТИРОВАТЬ. Обратите внимание, что даже если для модели восстановления задано значение Простой, журналы транзакций будут увеличиваться при массовом удалении. Журналы транзакций будут просто очищены после (без освобождения места). Идея состоит в том, что DELETE создаст транзакцию даже временно.

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

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

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

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

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

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

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

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

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