Обновление с «не в» на огромной таблице в SQL Server 2005 - PullRequest
3 голосов
/ 25 марта 2011

У меня есть таблица с примерно 115k строк. Примерно так:

Table: People
Column: ID PRIMARY KEY INT IDENTITY NOT NULL
Column: SpecialCode NVARCHAR(255) NULL
Column: IsActive BIT NOT NULL

Первоначально у меня был индекс, определенный так:

PK_IDX (clustered) -- clustered index on primary key
IDX_SpecialCode (non clustered, non-unique) -- index on the SpecialCode column

И я делаю обновление примерно так:

Update People set IsActive = 0 
Where SpecialCode not in ('...enormous list of special codes....')

Этот огромный список, по сути, составляет 99% пользователей в таблице.

Это обновление занимает навсегда на моем сервере. В качестве теста я урезал список специальных кодов в предложении «не в» примерно до 1% пользователей в таблице, и мой план выполнения заканчивается использованием INDEX SCAN для индекса PK_IDX вместо индекса IDX_SpecialCode, который я думал, что будет использовать.

Итак, я подумал, что, возможно, мне нужно изменить IDX_SpecialCode, чтобы он включал в себя столбец «IsActive». Я так и сделал, и я все еще вижу план выполнения по умолчанию при сканировании индекса PK_IDX, и мой запрос все еще занимает очень много времени.

Итак, что является более правильным способом сделать обновление такого рода? У меня есть список пользователей, которых я хочу исключить из обновления, но пытался не загружать специальные коды всех сотрудников из базы данных, отфильтровывать те, которых нет в моем списке на стороне приложения, а затем запускать мой запрос с предложением in , которое будет гораздо меньшим списком при моем фактическом использовании.

Спасибо

Ответы [ 4 ]

3 голосов
/ 25 марта 2011

Если у вас есть сотрудники, которых вы хотите исключить, почему бы просто не заполнить индексированную таблицу этими PK_ID и выполнить:

Update People 
set IsActive = 0 
Where NOT EXISTS (SELECT NULL
                  FROM lookuptable l
                  WHERE l.PK = People.PK)

Вы получаете сканирование индекса, потому что SQL Server не глуп и понимает,что имеет больше смысла просто просматривать всю таблицу, а не проверять 100 различных критериев по одному.Если ваша статистика актуальна, оптимизатор знает, сколько таблицы покрыто вашим оператором IN, и выполнит сканирование таблицы или кластерного индекса, если сочтет, что это будет быстрее.

1 голос
/ 25 марта 2011

При использовании SQL-сервера индексы игнорируются при использовании предложения NOT. Вот почему вы видите план выполнения, игнорирующий ваш индекс. <- См .: стр. 6. MCTS Exam 70-433 Разработка баз данных SQL 2008 (сейчас читаю) </p>

Возможно, стоит взглянуть на полнотекстовые индексы, хотя я не знаю, произойдет ли то же самое с этим (у меня нет доступа к блоку с его настройкой для тестирования в данный момент)

НТН

0 голосов
/ 25 марта 2011

Я думаю, что проблема ваша SpecialCode NVARCHAR(255). Сравнение строк в Sql Server очень медленное. Попробуйте изменить свой запрос для работы с идентификаторами. А также старайтесь избегать NVarchar. если вас не волнует Unicode, используйте Varchar.

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

0 голосов
/ 25 марта 2011

Можно ли каким-либо образом использовать идентификаторы пользователей, которых вы хотите исключить, вместо их кода - даже при индексированных значениях сравнение идентификаторов может выполняться быстрее, чем строки.

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