У меня есть таблица cats
с 42 795 120 строками.
Видимо, это много строк.Поэтому, когда я делаю:
/* owner_cats is a many-to-many join table */
DELETE FROM cats
WHERE cats.id_cat IN (
SELECT owner_cats.id_cat FROM owner_cats
WHERE owner_cats.id_owner = 1)
время ожидания запроса истекает: (
(редактировать: мне нужно увеличить значение CommandTimeout
по умолчанию только 30 секунд)
Я не могу использовать TRUNCATE TABLE cats
, потому что я не хочу выбрасывать кошек от других владельцев.
Яиспользуя SQL Server 2005 с параметром «Модель восстановления», установленным на «Простой».
Итак, я подумал о том, чтобы сделать что-то вроде этого (выполнить этот SQL из приложения):
DELETE TOP (25) PERCENT FROM cats
WHERE cats.id_cat IN (
SELECT owner_cats.id_cat FROM owner_cats
WHERE owner_cats.id_owner = 1)
DELETE TOP(50) PERCENT FROM cats
WHERE cats.id_cat IN (
SELECT owner_cats.id_cat FROM owner_cats
WHERE owner_cats.id_owner = 1)
DELETE FROM cats
WHERE cats.id_cat IN (
SELECT owner_cats.id_cat FROM owner_cats
WHERE owner_cats.id_owner = 1)
У меня вопрос: какой порог количества строк, которые я могу DELETE
в SQL Server 2005?
Или, если мой подход не является оптимальным, предложите лучший подход. Спасибо.
Этот пост мне не помог достаточно:
РЕДАКТИРОВАТЬ (06.08.2010):
Хорошо, я только что понял после прочтения вышеупомянутой ссылки, что у меня не было индексов на этихстолы. Также, сомВы уже указали на эту проблему в комментариях ниже.Имейте в виду, что это фиктивная схема, поэтому даже id_cat
не является PK, потому что в моей реальной жизненной схеме это не уникальное поле.
Я добавлю индексы:
cats.id_cat
owner_cats.id_cat
owner_cats.id_owner
Полагаю, я все еще изучаю это хранилище данных, и, очевидно, янужны индексы для всех полей JOIN
, верно?
Однако мне требуется несколько часов, чтобы выполнить этот процесс пакетной загрузки.Я уже делаю это как SqlBulkCopy
(кусками, а не 42 милами одновременно).У меня есть несколько индексов и ПК.Я прочитал следующие посты, которые подтверждают мою теорию о том, что индексы замедляются даже при массовом копировании:
Итак, я собираюсь DROP
мои индексы перед копированием, а затем повторно CREATE
их, когдаэто сделано.
Из-за продолжительного времени загрузки мне потребуется некоторое время, чтобы проверить эти предложения.Я сообщу с результатами.
ОБНОВЛЕНИЕ (8/7/2010):
Том предложил:
DELETE
FROM cats c
WHERE EXISTS (SELECT 1
FROM owner_cats o
WHERE o.id_cat = c.id_cat
AND o.id_owner = 1)
И все жебез индексов для 42 миллионов строк это заняло 13:21 мин: сек против 22:08, как описано выше.Однако за 13 миллионов строк он занял 2:13 против 2:10 по-старому.Это хорошая идея, но мне все еще нужно использовать индексы!
Обновление (08.08.2010):
Что-то ужасно неправильно!Теперь при включенных индексах мой первый запрос на удаление, приведенный выше, занял 1: 9 часов: мин (да, час!) против 22:08 мин: с и 13:21 мин: спротив 2:10 мин: сек для 42 милов строк и 13 мил рядов соответственно.Я собираюсь попробовать запрос Тома с индексами сейчас, но это движется в неправильном направлении.Пожалуйста, помогите.
Обновление (9/9/2010):
Удаление Тома заняло 1:06 часа: мин для 42 млн строк и 10:50 мин: секдля 13 мил строк с индексами против 13:21 мин: сек и 2:13 мин: сек соответственно. Удаление занимает больше времени в моей базе данных, когда я использую индексы на порядок! Мне кажется, я знаю, почему, моя база данных .mdf и .ldf выросла с 3,5 ГБ до 40,6 ГБ за времяпервое (42 мил) удаление! Что я делаю не так?
Обновление (10/10/2010):
Из-за отсутствия каких-либо других опций я подошелс тем, что я считаю слабым решением (надеюсь, временным) :
- Увеличение времени ожидания для подключения к базе данных до 1 часа (
CommandTimeout=60000;
по умолчанию было 30 секунд) - Используйте запрос Тома:
DELETE FROM WHERE EXISTS (SELECT 1 ...)
, потому что он выполнялся немного быстрее DROP
всех индексов и PK перед запуском оператора удаления (???) - Выполнить
DELETE
оператор CREATE
все индексы и PK
Кажется сумасшедшим, но по крайней мере это быстрее, чем использовать TRUNCATE
и начинать с моей нагрузки с самого начала с первого owner_id
, потому что одному из моих owner_id
требуется 2:30 часа: мин для загрузки против 17:22min: sec для процесса удаления, который я только что описал с 42 млн строк.(Примечание: если мой процесс загрузки выдает исключение, я начинаю заново для этого owner_id
, но я не хочу отбрасывать предыдущий owner_id
, поэтому я не хочу TRUNCATE
таблицу owner_cats
,вот почему я пытаюсь использовать DELETE
.)
Больше помощи все равно будет приветствоваться:)