Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: 1 2 3      [все]
 WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
Доброго всем дня.
Может кто нибудь подскажет, почему вот примерно такая вот кострукция

select top 10 *
from table1 t1
join table2 t1
on...
там еще с 10 join
where t1.f1 not in (select f2 from table2)

может работать значительно быстрее, чем

select top 10 *
from table1 t1
join table2 t1
on...
там еще с 10 join
where t1.f1 not in (select f2 from table2 WITH(NOLOCK))

Немного деталей
1. Запросы отличаются только хинтом WITH(NOLOCK)
2. Планы у запросов одинаковые
3. SET STATISTICS IO показывает, что запрос без WITH(NOLOCK) делает больше логических чтений по table2
4. Профайлер показывает значительно большее количество чтений для запроса с WITH(NOLOCK).
13 ноя 14, 14:00    [16840096]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
Glory
Member

Откуда:
Сообщений: 104751
SergeyPK
Немного деталей
1. Запросы отличаются только хинтом WITH(NOLOCK)
2. Планы у запросов одинаковые
3. SET STATISTICS IO показывает, что запрос без WITH(NOLOCK) делает больше логических чтений по table2
4. Профайлер показывает значительно большее количество чтений для запроса с WITH(NOLOCK).

Вы кэш очищали при ваших экспериментах ?
13 ноя 14, 14:02    [16840114]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
Glory
SergeyPK
Немного деталей
1. Запросы отличаются только хинтом WITH(NOLOCK)
2. Планы у запросов одинаковые
3. SET STATISTICS IO показывает, что запрос без WITH(NOLOCK) делает больше логических чтений по table2
4. Профайлер показывает значительно большее количество чтений для запроса с WITH(NOLOCK).

Вы кэш очищали при ваших экспериментах ?

Нет. Но запускал раз с десяток каждый. На обоих запросах были только логичесие чтения.
13 ноя 14, 14:08    [16840159]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
Glory
SergeyPK
Немного деталей
1. Запросы отличаются только хинтом WITH(NOLOCK)
2. Планы у запросов одинаковые
3. SET STATISTICS IO показывает, что запрос без WITH(NOLOCK) делает больше логических чтений по table2
4. Профайлер показывает значительно большее количество чтений для запроса с WITH(NOLOCK).

Вы кэш очищали при ваших экспериментах ?

Почистил. Запустил без WITH(NOLOCK). Быстро отработал.
Почистил. Запустил с WITH(NOLOCK). Отработал медленно.
13 ноя 14, 14:15    [16840212]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
Glory
Member

Откуда:
Сообщений: 104751
SergeyPK
Почистил. Запустил без WITH(NOLOCK). Быстро отработал.
Почистил. Запустил с WITH(NOLOCK). Отработал медленно.

И как другим это воспроизвести у себя ?
13 ноя 14, 14:16    [16840223]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
Glory
SergeyPK
Почистил. Запустил без WITH(NOLOCK). Быстро отработал.
Почистил. Запустил с WITH(NOLOCK). Отработал медленно.

И как другим это воспроизвести у себя ?

Да никак.
Вопрос не в том, как улучшить. Вопрос - почему так может быть? Ну или куда смотреть, чтоб понять разницу в скорости выполнения?
13 ноя 14, 14:27    [16840315]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
Glory
Member

Откуда:
Сообщений: 104751
SergeyPK
Да никак.

А как можно "понять разницу в скорости выполнения" того, что нельзя воспроизвести ?
13 ноя 14, 14:30    [16840342]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 8725
А почему Вы объединяете с read committed, а читаете с read uncommitted?
13 ноя 14, 14:34    [16840381]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
Glory
SergeyPK
Да никак.

А как можно "понять разницу в скорости выполнения" того, что нельзя воспроизвести ?

Glory, Я отлично понимаю, что без доступа к реальным данным никто кроме меня это не воспроизведет.
Поэтому мне нужна только подсказка, в какую сторону смотреть. Может кто-то когда-то сталкивался или читал про такое странное поведение.
Вопрос скорее чисто теоретический. Как хинт WITH(NOLOCK) может значительно замедлить выполнение запроса. При этом планы одинаковые.
13 ноя 14, 14:35    [16840394]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
o-o
Guest
может, какая-то фигня из серии, когда идет выборка с with (nolock),
то вместо сканирования в порядке кластерного индекса, выбралось в порядке распределения?
и как-то хитро страницы разложились, что так оказалось еще и дольше?
(извините, если бред)
13 ноя 14, 14:37    [16840406]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
iap
Member

Откуда: Москва
Сообщений: 47105
Владислав Колосов
А почему Вы объединяете с read committed, а читаете с read uncommitted?
А где там read committed?
Вообще говоря, неизвестно, что там происходит без хинта NOLOCK.
13 ноя 14, 14:37    [16840407]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
Glory
Member

Откуда:
Сообщений: 104751
SergeyPK
При этом планы одинаковые.

Ну вы же сами сказали, что SET STATISTICS IO разные

SergeyPK
Glory, Я отлично понимаю, что без доступа к реальным данным никто кроме меня это не воспроизведет.

Для воспроизведения не нужны реальные данные вашей конторы. Подойдут любые данные.
13 ноя 14, 14:38    [16840425]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 8725
iap,

Если автор не указывает уровень изоляции, то я рассматриваю по умолчанию.
13 ноя 14, 14:43    [16840471]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
Владислав Колосов
А почему Вы объединяете с read committed, а читаете с read uncommitted?

Сорри
изначально было вот так

select top 10 *
from table1 t1
join table2 t1 WITH(NOLOCK)
on...
там еще с 10 join
where t1.f1 not in (select f2 from table2 WITH(NOLOCK))

Забыл вставит первый WITH(NOLOCK). Но для моего вопроса это не принципиально.
Запрос ниже, где WITH(NOLOCK) только в NOT IN, работает так же медлено.

select top 10 *
from table1 t1
join table2 t1
on...
там еще с 10 join
where t1.f1 not in (select f2 from table2 WITH(NOLOCK))
13 ноя 14, 14:43    [16840475]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 8725
SergeyPK,

значит планы разные. Приведите полноценный пример, который бы доказывал Ваше утверждение о различии времени запроса.
13 ноя 14, 14:48    [16840520]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
Glory
SergeyPK
При этом планы одинаковые.

Ну вы же сами сказали, что SET STATISTICS IO разные

SergeyPK
Glory, Я отлично понимаю, что без доступа к реальным данным никто кроме меня это не воспроизведет.

Для воспроизведения не нужны реальные данные вашей конторы. Подойдут любые данные.


SET STATISTICS IO действительно разные. При этом по всем таблицам одинаковые, кроме table2. NТот запрос, который без NOLOCK и выполняется быстрее, показывает большее количество логических чтений. Для меня это странно.

В приципе могу попробовать создать похожую структуру и набить фейковыми данными. Но тавлиц в join-ах много. Данных достаточно много. Дело не одного дня.
Реальные данные заказчик кому либо другому предоставить не разрешит.
13 ноя 14, 14:51    [16840549]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
Владислав Колосов
iap,

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

Да, по умолчанию. COMMITTED
13 ноя 14, 14:53    [16840564]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
Glory
Member

Откуда:
Сообщений: 104751
SergeyPK
В приципе могу попробовать создать похожую структуру и набить фейковыми данными. Но тавлиц в join-ах много. Данных достаточно много. Дело не одного дня.
Реальные данные заказчик кому либо другому предоставить не разрешит.

Вы предлагаете удаленно определить, что у вас происходит ? И поверить в цифры, которые видите только вы ?
13 ноя 14, 14:53    [16840572]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
iap
Member

Откуда: Москва
Сообщений: 47105
Владислав Колосов
iap,

Если автор не указывает уровень изоляции, то я рассматриваю по умолчанию.
Изоляция по-умолчанию настраивается. ЕМНИП.

SergeyPK, задавайте хинт явно, а не просто убирайте его.
И никогда не пишите NOT IN(SELECT ...).
Попадётся в подселекте NULL, - и попадёте.
13 ноя 14, 14:54    [16840581]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
Владислав Колосов
SergeyPK,

значит планы разные. Приведите полноценный пример, который бы доказывал Ваше утверждение о различии времени запроса.

К сожалению не могу привести пример прямо сейчас. Как будет свободное время, попробую сделать что-то воспроизводимое.
Но поверте мне на слово. Планы одинаковые. По крайней мере сервер мне дает такой же самый актуальный план на оба запроса.
13 ноя 14, 14:56    [16840595]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
invm
Member

Откуда: Москва
Сообщений: 9785
SergeyPK,

Лучше планы реальные опубликуйте. В формате sqlplan.
Толку будет гораздо больше.
13 ноя 14, 14:57    [16840605]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
invm
Member

Откуда: Москва
Сообщений: 9785
SergeyPK
Планы одинаковые. По крайней мере сервер мне дает такой же самый актуальный план на оба запроса.
И как вы в этом убедились? Анализирую глазами?
13 ноя 14, 14:58    [16840618]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
Glory
Member

Откуда:
Сообщений: 104751
SergeyPK
. Планы одинаковые. По крайней мере сервер мне дает такой же самый актуальный план на оба запроса.

Вы их визуально сравнивали ? Или в текстовом виде вплоть до числа выбираемых записей и чмсла выполнений ?
Потому что Nested Loops везде выглядит одинаково, но 10 выполнений и 1000000 очень сильно влияеют на время выполнения и число чтений
13 ноя 14, 14:59    [16840622]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
Glory
SergeyPK
В приципе могу попробовать создать похожую структуру и набить фейковыми данными. Но тавлиц в join-ах много. Данных достаточно много. Дело не одного дня.
Реальные данные заказчик кому либо другому предоставить не разрешит.

Вы предлагаете удаленно определить, что у вас происходит ? И поверить в цифры, которые видите только вы ?

Glory, уважаемый. Еще раз повторю. Мне не нужно, чтоб кто-то что-то у меня определил. Чисто теоретический вопрос

автор
Поэтому мне нужна только подсказка, в какую сторону смотреть. Может кто-то когда-то сталкивался или читал про такое странное поведение.
Вопрос скорее чисто теоретический. Как хинт WITH(NOLOCK) может значительно замедлить выполнение запроса. При этом планы одинаковые.
13 ноя 14, 15:00    [16840628]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
Glory
Member

Откуда:
Сообщений: 104751
SergeyPK
Glory, уважаемый. Еще раз повторю. Мне не нужно, чтоб кто-то что-то у меня определил. Чисто теоретический вопрос

Какой вопрос то ?
Меня волнуют цифирки на экране ? Мне кажется, что они неправильные ?
13 ноя 14, 15:03    [16840660]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
iap
Владислав Колосов
iap,

Если автор не указывает уровень изоляции, то я рассматриваю по умолчанию.
Изоляция по-умолчанию настраивается. ЕМНИП.

SergeyPK, задавайте хинт явно, а не просто убирайте его.
И никогда не пишите NOT IN(SELECT ...).
Попадётся в подселекте NULL, - и попадёте.

В курсе. Именно поэтому у нас на проекте сейчас и пересматривают весь этот код, что до нас наваяли.
Там много чиго, что мне не нравится. Но вопрос у меня сейчас больше теоретический. Чисто для моего знания и понимания.
13 ноя 14, 15:03    [16840664]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
invm
SergeyPK
Планы одинаковые. По крайней мере сервер мне дает такой же самый актуальный план на оба запроса.
И как вы в этом убедились? Анализирую глазами?

Даже сравнил Винмержем. :)
13 ноя 14, 15:05    [16840677]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
Glory
SergeyPK
. Планы одинаковые. По крайней мере сервер мне дает такой же самый актуальный план на оба запроса.

Вы их визуально сравнивали ? Или в текстовом виде вплоть до числа выбираемых записей и чмсла выполнений ?
Потому что Nested Loops везде выглядит одинаково, но 10 выполнений и 1000000 очень сильно влияеют на время выполнения и число чтений

Или в текстовом виде вплоть до числа выбираемых записей и чмсла выполнений.
13 ноя 14, 15:11    [16840730]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
Glory
SergeyPK
Glory, уважаемый. Еще раз повторю. Мне не нужно, чтоб кто-то что-то у меня определил. Чисто теоретический вопрос

Какой вопрос то ?
Меня волнуют цифирки на экране ? Мне кажется, что они неправильные ?

Вопрос простой.
2 запроса. Отличаются только хинтом на одной таблице. Планы одинаковые. А время выполнение разное. Почему?
Отлично понимаю, что без реального примера врядли кто поможет. Но вдруг.
13 ноя 14, 15:18    [16840771]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
Павел-П
Member

Откуда:
Сообщений: 234
Мне кажется, что чисто теоретически with (nolock), как и установка любого другого уровня изоляции транзакции на план влиять не должно. Но я тут могу ошибаться. Думаю, знающие люди могут поправить.
13 ноя 14, 15:25    [16840828]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
Павел-П
Мне кажется, что чисто теоретически with (nolock), как и установка любого другого уровня изоляции транзакции на план влиять не должно. Но я тут могу ошибаться. Думаю, знающие люди могут поправить.

Может влиять. Сталкивался с таким.
13 ноя 14, 15:26    [16840840]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
Павел-П
Member

Откуда:
Сообщений: 234
SergeyPK
Павел-П
Мне кажется, что чисто теоретически with (nolock), как и установка любого другого уровня изоляции транзакции на план влиять не должно. Но я тут могу ошибаться. Думаю, знающие люди могут поправить.

Может влиять. Сталкивался с таким.


А пример привести можете. Ну или ссылочку, чтобы людям было полезно.
13 ноя 14, 15:28    [16840858]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
Павел-П
Member

Откуда:
Сообщений: 234
SergeyPK
Glory
пропущено...

Какой вопрос то ?
Меня волнуют цифирки на экране ? Мне кажется, что они неправильные ?

Вопрос простой.
2 запроса. Отличаются только хинтом на одной таблице. Планы одинаковые. А время выполнение разное. Почему?
Отлично понимаю, что без реального примера врядли кто поможет. Но вдруг.


А запросы на нагруженной системе выполняются. Изолируйте ваши 2 запроса от окружающего мира и выполните.
13 ноя 14, 15:29    [16840870]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
Павел-П
SergeyPK
пропущено...

Вопрос простой.
2 запроса. Отличаются только хинтом на одной таблице. Планы одинаковые. А время выполнение разное. Почему?
Отлично понимаю, что без реального примера врядли кто поможет. Но вдруг.


А запросы на нагруженной системе выполняются. Изолируйте ваши 2 запроса от окружающего мира и выполните.

На изолированной.
P.S. Пример с разными планами попробую найти.
13 ноя 14, 15:47    [16841025]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
o-o
Guest
Павел-П
SergeyPK
...чисто теоретически with (nolock), как и установка любого другого уровня изоляции транзакции на план влиять не должно...
Может влиять. Сталкивался с таким.

А пример привести можете. Ну или ссылочку, чтобы людям было полезно.

вот не чтоб именно план, а порядок вычитывания менялся из-за использования with (nolock), на такое могу ссылку дать.
время-то поди разное будет у вычитки, но только в другую сторону...
When can allocation order scans be used?
13 ноя 14, 15:52    [16841080]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
invm
Member

Откуда: Москва
Сообщений: 9785
o-o,

У ТС (по его словам) физических чтений нет.


SergeyPK,

Ваш товарищ по несчастью - http://www.sqlservercentral.com/Forums/Topic1230597-149-1.aspx
13 ноя 14, 16:01    [16841163]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
invm
o-o,

У ТС (по его словам) физических чтений нет.


SergeyPK,

Ваш товарищ по несчастью - http://www.sqlservercentral.com/Forums/Topic1230597-149-1.aspx

Походу да. Ситуация один в один.
13 ноя 14, 16:21    [16841365]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
Гавриленко Сергей Алексеевич
Member

Откуда: Moscow
Сообщений: 37254
Давайте выясним версию вашего сервера.
13 ноя 14, 16:36    [16841508]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
Гавриленко Сергей Алексеевич
Давайте выясним версию вашего сервера.

Сорри. Забыл сразу запостать.
Microsoft SQL Server 2008 (SP3) - 10.0.5846.0 (X64)
Aug 26 2013 09:39:36
Copyright (c) 1988-2008 Microsoft Corporation
Standard Edition (64-bit) on Windows NT 6.2 <X64> (Build 9200: )
13 ноя 14, 16:44    [16841593]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
Павел-П
SergeyPK
пропущено...

Может влиять. Сталкивался с таким.


А пример привести можете. Ну или ссылочку, чтобы людям было полезно.


Черт, пытался вспомнить где у меня это было. Вспомнил, нашел, обрадовался. Потом расстроился.
Я добавлял это хинт в связке FTS (CONTAINSTABLE) + join на таблицу.
Только что проверил еще раз. План время от времени меняется. Ну, думаю, оно. Ан нет. Просто там сам по себе план нестабильный генерится. Даже если я поменяю алиас на таблице - может сгенерится другой.
Так что снимаю свое утверждение.
P.S. Коллега вот рядом утверждает, что видел такое с WITH NOLOCK. Но лениться вспомнить где и воспроизвести.
13 ноя 14, 18:30    [16842239]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SIMPLicity_
Member

Откуда: (((@)))
Сообщений: 8863
Паразитный параллелизм?, как вариант - с афигительной нагрузкой, например, на tempdb?...
14 ноя 14, 05:25    [16843731]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
SIMPLicity_
Паразитный параллелизм?, как вариант - с афигительной нагрузкой, например, на tempdb?...

Что значит "паразитный"? В плане параллелизма нет.
14 ноя 14, 10:08    [16844288]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
Владимир Затуливетер
Member

Откуда:
Сообщений: 427
уважаемый ТС,
я вот поражаюсь, что планы обоих запросов выложить не судьба или хотябы сравнить?
уже вроде как два раза просили.
с большой долей вероятности можно сказать что планы будут разные.
меняете запрос - может поменяться и план, это естественное поведение для sql server.
14 ноя 14, 14:06    [16846325]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
Владимир Затуливетер
уважаемый ТС,
я вот поражаюсь, что планы обоих запросов выложить не судьба или хотябы сравнить?
уже вроде как два раза просили.
с большой долей вероятности можно сказать что планы будут разные.
меняете запрос - может поменяться и план, это естественное поведение для sql server.

Уважаемый Владимир Затуливетер, я вот поражаюсь, Вы вроде весь топик прочитали.
Выложить планы мне не позволяет соглашение с заказчиком. Могу Вас уверить, они совпадают от первой до последней буквы(цифры) во всем, кроме самого текста запроса. Лично сравнил 3 раза в WinMerge.
Если уж стопроцентно хотите убедится, что это так, то внизу я приведу ссылку, где описана точно такая же проблема и есть планы.

http://www.sqlservercentral.com/Forums/Topic1230597-149-1.aspx
14 ноя 14, 14:35    [16846612]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
Спасибо за интересный вопрос.

Для желающих пощупать лично

Проверял на версиях:
- Microsoft SQL Server 2014 - 12.0.2342.0 (X64)
- Microsoft SQL Server 2012 (SP1) - 11.0.3153.0 (X64)
- Microsoft SQL Server 2008 (RTM) - 10.0.1779.0 (X64)

Проявляется везде, но могут быть разные условия.

2014 – требуется старая версия Cardinality Estimation Framework, которая включается документированным трейс флагом 9481 или уровнем совместимости БД с 2012 или более ранней версией. Иначе, план имеет другую форму и особенность не проявляется явно, а именно оба запроса работают одинаково плохо =)

2012 – В силу разницы внутренних эвристик, для той же стоимости применяется дополнительное правило и в плане появляется лишний Spool который избавляет от проблемы. В таком случае, для воспроизведения репро, требуется просто уменьшить число строк, чтобы дополнительная оптимизация со Spool не возникала (число подбирается эмпирически, глядя на план, у меня получились цифры где-то около t1 - 30 000 и t2 - 100 000).

2008 RTM – Дополнительно ничего делать не требуется

Репро (для 2014):
+
create database test;
go
use test;
go
if object_id('t1') is not null drop table t1;
if object_id('t2') is not null drop table t2;
go
create table t1(a int primary key identity, b int, c char(350) not null default(''));
create table t2(a int primary key identity, b int, c char(50) not null default(''));
go
with c as (
	select top(50000) rn=row_number() over(order by(select null)) from master..spt_values v1,master..spt_values v2,master..spt_values v3
)
insert into t1(b)
select convert(varchar(10), rn) from c;

with c as (
	select top(150000) rn=row_number() over(order by(select null)) from master..spt_values v1,master..spt_values v2,master..spt_values v3
)
insert into t2(b)
select rn from c
go
dbcc traceon(9481); -- Enable OLD CE
dbcc freeproccache; -- WARNING!!! clear cache.
go


set statistics time, xml, io on;
select * from t1 where b not in (select b from t2) option(maxdop 1);
select * from t1 where b not in (select b from t2 with(nolock)) option(maxdop 1);
set statistics time, xml, io off;
go


Результаты (время):
CPU time = 234 ms,  elapsed time = 394 ms.
CPU time = 5258 ms,  elapsed time = 5338 ms.

Более чем в 10 (!) раз медленнее, можно подобрать так, что разница будет в 100 и более раз.

Объяснение
Наверное, многим известно, что когда Query Processor (QP) не запрашивает сканирование индекса в определённом порядке, у Storage Engine (SE) есть две стратегии, как получить данные:
- Сканирование страниц в порядке ключа индекса (Index Order Scan)
- Сканирование страниц по картам размещения (Allocation/IAM Scan)

Для второго, помимо отсутствия требований к сортировке еще важно, чтобы данные не могли измениться в процессе сканирования – tablock, или их изменение было не важным – nolock (репро работает как с одним, так и с другим хинтом).

Теперь, посмотрим на план:
Картинка с другого сайта.

Два слова о плане в целом, а именно, почему такая сложная форма.

Дело в конструкции not in () и nullable колонке b. QP, должен обеспечить условие, если в подмножестве, которое проверятся на включение обнаружится хотя бы один null – запрос не должен ничего возвращать. Если попробовать переписать запрос через not exists, то план изменится, разница во времени исчезнет, а план станет гораздо проще.
set statistics time, xml, io on;
select * from t1 where not exists (select b from t2 where t1.b = t2.b) option(maxdop 1);
select * from t1 where not exists (select b from t2 with(nolock) where t1.b = t2.b) option(maxdop 1);
set statistics time, xml, io off;
go


Теперь, обратим внимание на выделенную часть TOP + Clustered Index Scan.

Оператор TOP, присутствует в плане, хотя мы не использовали TOP в запросе, т.к. это внутренняя оптимизация, (оправданная в данном случае и если ее отключить, оба запроса станут очень медленными), которая используется сервером для того, чтобы не сканировать весь индекс целиком, а взять только одну строку, ведь мы проверяем только вхождение – это то, о чем говорит верхний оператор Left Anti Semi Join.

Далее то, что в планах не показывается, а именно, то, как SE начинает сканирование в случае Index Order Scan и Allocation Scan.

Для Index Order Scan – север находит только первую страницу индекса и сразу начинает читать записи.
Для Allocation Order Scan – сервер проходит по всей цепочке IAM и только потом начинает чтение, хотя нужна ему по сути только одна страница.

Я попытался проиллюстрировать это на картинках (очень упрощенно):
Картинка с другого сайта.

Если попытаться сделать репро попроще, мы увидим тот же эффект (для форсирования нужной формы плана я использовал Force Order).
set statistics io, time on;
declare @a int;
select @a = t1.a from t1 cross apply (select top(1) b from t2) t2 option(force order, maxdop 1)
select @a = t1.a from t1 cross apply (select top(1) b from t2 with(nolock)) t2 option(force order,  maxdop 1)
set statistics io, time off;


Время:
CPU time = 93 ms,  elapsed time = 91 ms.
CPU time = 5133 ms,  elapsed time = 5138 ms.


При этом, интересным образом отображается число чтений =) Для Index Order Scan в статистику попадают все уровни, и получается 3 (глубина индекса) * 50 000 (запросов по одной странице) = 150 000 чтений. А для Allocation Order Scan страницы IAM не попадают в статистику, и получается 50 000. Выглядит парадоксально, чтений меньше, а времени больше!

Откуда время CPU? Дело в количестве инструкций, которые необходимо выполнить серверу, для того, чтобы найти либо одну страницу индекса, либо проинициализировать каждую страницу IAM.

Статистика по инструкциям из WinDbg, по получению одной (!) строки для Nested Loops (Left Anti Semi Join):
Index Order Scan: 22516 instructions
Allocation Scan: 641340 instructions
Теперь, помножить это на 50 000 и будет понятно, куда тратится процессорное время.

+ Для гиков

Если желаете пронаблюдать разницу в количестве действий, выкладываю два Call Tree для одного и другого случая в формате XML (я обычно открываю такое в XML Notepad).
Call Trees ZIP (12.5 KB)


Резюме
Чтобы не попадать в такие проблемы, нужно следовать хорошим практикам, а именно, объявлять колонки not null если там не может быть null, а если может быть null использовать not exists, ну и не использовать nolock без надобности, как «ускоритель».

Написал по мотивам Sql Server Central, т.к. там хотя бы есть планы, из которых можно все это раскрутить. ТС планы не предоставил, так что возможно у него что-то другое, но раз он сам сослался на SSC, будем считать, что тоже самое применимо и к случаю ТС.
16 ноя 14, 19:10    [16854682]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
Павел-П
Member

Откуда:
Сообщений: 234
SomewhereSomehow,

Большое спасибо за потраченное время и усилия на предыдущий пост.
16 ноя 14, 22:20    [16855320]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
Knyazev Alexey
Member

Откуда: Екб -> Мск
Сообщений: 10233
Блог
SomewhereSomehow
Спасибо за интересный вопрос.


БРАВО!!!
17 ноя 14, 02:35    [16856017]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
SomewhereSomehow
Спасибо за интересный вопрос.

Написал по мотивам Sql Server Central, т.к. там хотя бы есть планы, из которых можно все это раскрутить. ТС планы не предоставил, так что возможно у него что-то другое, но раз он сам сослался на SSC, будем считать, что тоже самое применимо и к случаю ТС.

SomewhereSomehow. Спасибо Вам большое!!! Теперь в голове все легло на свои полочки.
P.S. Планы действительно не могу предоставить по полиси. :(
17 ноя 14, 10:46    [16856918]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SergeyPK
Member

Откуда:
Сообщений: 44
Отдельное спасибо invm за предоставленную ссылку.
17 ноя 14, 10:49    [16856935]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
WarAnt
Member

Откуда: Питер
Сообщений: 2423
SomewhereSomehow,

Очень познавательно, спасибо!
17 ноя 14, 12:17    [16857587]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2322
SomewhereSomehow,

Великолепно! Спасибо за проделанную работу!
17 ноя 14, 20:59    [16861827]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
Mike_za
Member

Откуда: Москва
Сообщений: 1176
SomewhereSomehow, спсибо!!!))
25 фев 15, 00:49    [17307979]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
IAM Scan
Guest
А как определить, какой из сканов Index Order Scan или Allocation/IAM Scan использовался в запросе?
16 июл 15, 08:49    [17897911]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
Arm79
Member

Откуда: МО, Раменское
Сообщений: 3695
SomewhereSomehow, супер. Спасибо.
16 июл 15, 19:58    [17901581]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
o-o
Guest
извиняюсь за поднятие старой темы по прошествии чуть ли не года,
просто на нее сослался invm из свежей темы.
и хочу я спросить, что означает в данном случае IAM chain,
словами и на картинке.
в моем понимании IAM-страницы объединяются в цепочки,
когда одному объекту соответствует белее одной IAM-страницы.
ну там таблица размазана по нескольким файлам, или размером не вышла: вылезла за 4Гб,
или присутствует секционирование, или там IN_ROW_DATA, LOB_DATA, ROW_OVERFLOW_DATA.
но я беру репро прямо из этого топика, у меня сервер 2008 R2,
поэтому никаких изменений не вношу, запускаю как есть, наблюдаю эффект.
в то же время не наблюдаю никаких IAM-цепочек.
2 таблицы -- 2 IAM-страницы, по одной на каждую таблицу.
откуда бы взяться цепочкам, если база имеет один файл данных, таблицы не переваливают за 4Гб,
секционирования нет, аllocation units тоже только IN_ROW_DATA?
поясните пожалуйста.
заранее спасибо

SomewhereSomehow
Для Index Order Scan – север находит только первую страницу индекса и сразу начинает читать записи.
Для Allocation Order Scan – сервер проходит по всей цепочке IAM и только потом начинает чтение, хотя нужна ему по сути только одна страница.

Я попытался проиллюстрировать это на картинках (очень упрощенно):
Картинка с другого сайта.
8 авг 16, 13:35    [19515537]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
http://www.queryprocessor.com/nolock-and-top-optimization/
8 авг 16, 14:34    [19515874]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
o-o
Guest
так что-то там картинка поменялась и никаких IAM-цепочек и в помине нет
(а тут эти цепочки указаны как ПРИЧИНА)
тогда как же всем все было ясно?

К сообщению приложен файл. Размер - 45Kb
8 авг 16, 14:42    [19515917]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
o-o
Guest
тогда уточнение терминологии.
правильно ли я на этот раз понимаю,
что дело не в зеленых стрелках к страницам листового уровня,
а в *интерпретации* пусть даже и одной IAM-страницы?
т.е. вот эту самую битмапину надо *каждый раз полностью* расшифровывать,
ну т.е. там бит выколот или нет, а надо всего 1 страницу,
так он не в состоянии нужный бит проверить, высчитывает для каждого экстента,
allocated он или нет?
8 авг 16, 14:51    [19515969]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
SomewhereSomehow
http://www.queryprocessor.com/nolock-and-top-optimization/

Да, если кто-то сохранил себе куда-то эту тему, на всякий случай, поясню. В первый раз, я немного не туда посмотрел, перепутал. В блоге, разумеется, я это учел, но поднимать из-за этого старую тему счел бессмысленным. Суть проблемы остается одной и той же, но детали в блоге описаны более правильно, так что вместо ссылки на тему, лучше использовать ссылку на блог.
8 авг 16, 15:57    [19516460]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
o-o
Guest
спасибо
---
по-моему, стОило старую тему поднять,
потому что
1) это интересная тема и ее помнят и будут продолжать цитировать
в отличие от тем "как получить 1 января в аксессе",
поэтому актуальная информация прямо в теме не помешала бы
2) кто ж кроме вас мог знать, что надо в блоге пошариться,
ведь в теме нет прямой ссылки на нужную статью
(уже есть :)
8 авг 16, 16:04    [19516510]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
iljy
Member

Откуда:
Сообщений: 8711
o-o,

согласен, тема действительно классная. Но у меня возник немного другой вопрос, уже по самому плану.


SomewhereSomehow

В блоге объясняется, что проблемная ветка Nested Loop предназначена для решения ситуации, когда в t2 есть NULL (тогда ничего не должно быть возвращено). Но сдается мне, что эту проблему решает следующий цикл, который с Row Count Spool. Именно в ней у операции Clustered Index Scan присутствует предикат [NoLockDB].[dbo].[t2].[b] IS NULL. А ветка, про которую речь, отрабатывает другую ситуацию - null выводится, только если запрос внутри not in не возвращает ничего:

select *
from (values (null),(0),(2)) t(x)
where x not in (select * from (values(0),(1)) tt(xx) where xx > 100)


На эту мысль меня навел предикат в Nested Loop ([NoLockDB].[dbo].[t1].[b] IS NULL), т.е. строка с t1.b is NULL проходит дальше, только если в t2 пусто.


И в итоге по плану запроса у меня возникли такие вопросы:

1. Почему в проблемной ветке TOP, а не Row Count Spool? Тут нам надо просто знать, есть ли такие строки, зачем тыкать в таблицу каждый раз вместо одной проверки?
2. Проблемная ветка вообще не должна выполняться для [t1].[b] IS NOT NULL, почему ее не отсечь фильтром запуска? Ибо - зачем тыкать 35 тысяч раз в таблицу, если это вообще не нужно?
8 авг 16, 22:27    [19517994]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
iljy,

Добрый день.

В блоге не объясняется, какая ветка плана за какое условие отвечает, это не цель статьи. Просто говорится, чем обусловлен такой сложный план, который содержит всего две таблицы, в частности, той проблемой, что запрос ничего не должен возвращать, если в подзапросе встретится NULL. Эффект с NULL в not in() ярко демонстрирует ситуацию, когда запрос перестает работать так, как задумал программист и почему не надо писать такие запросы.

Если интересно, какая ветка, за какое именно условие отвечает, это легко можно увидеть таким способом, прямо в этом же примере:

select * from t1 where b not in (select b from t2) option(maxdop 1);
select * from t1 where isnull(b,1) not in (select b from t2) option(maxdop 1);
select * from t1 where b not in (select isnull(b,1) from t2) option(maxdop 1);
select * from t1 where isnull(b,1) not in (select isnull(b,1) from t2) option(maxdop 1);

+
Картинка с другого сайта.

Ветка с TOP действительно обрабатывает условие, если на внешней стороне NL строка с NULL, то проверить, есть ли что-то на внутренней стороне.

По вопросам. Предикат применяется ко внешнему входу, не ко внутреннему, если делать Row Count Spool, то придется каждый раз читать всю таблицу и считать строки, это очень дорого. В противоположность, когда Row Count Spool используется в следующей ветке, где ко внутреннему входу можно применить предикат b IS NULL и далее уже просто проверять наличие строк в Spool. План с Row Count Spool тем не менее возможен, попробуйте посмотреть план:
select * from t1 where b not in (select b from t2) option(maxdop 1, queryruleoff BuildTop);

Картинка с другого сайта.

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

Что касается Start Up фильтра, то не вижу теоретической невозможности его добавить, возможно это упущение, а возможно причина стоимостная.
9 авг 16, 12:39    [19519680]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
SomewhereSomehow,

В дополнение по форме плана, раз это оказалось интересно, скажу что такая форма порождена оптимизацией, а не необходимостью.
В самом простейшем случае, когда строк мало:
declare @t1 table (b int);
declare @t2 table (b int);
select * from @t1 where b not in (select b from @t2);

План получается также простой:
Картинка с другого сайта.
С простым и понятным предикатом.
Когда строк становится много, такой план получается слишком дорогим, поэтому начинаются ухищрения.
Можно отключить правила оптимизации, которые делают эти ухищрения, чтобы получить простую форму и сравнить стоимости:
select * from t1 where b not in (select b from t2) option(maxdop 1);
select * from t1 where b not in (select b from t2) option(maxdop 1, queryruleoff SplitLASJN, queryruleoff BuildSpool);

Первый весит 12.7057 юнитов, второй 34563.3. Что отражается в SSMS в стоимости запросов относительно друг друга даже как 0% к 100% =)
Картинка с другого сайта.
9 авг 16, 12:59    [19519799]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
iljy
Member

Откуда:
Сообщений: 8711
SomewhereSomehow,

по поводу не писать такие запросы - этому учишься очень быстро :) Просто заинтересовали некоторые особенности плана, решил копнуть.
Понятно, что просто RowCount будет дорого, но ведь он может сочетаться с TOP. Это сочетание легко получить, если добавить в t2 несколько нулов, тогда во второй ветке TOP появится. Просто удивило, что в одном случае сервер додумывается до такой оптимизации, а в другом - увы.
Про StartUp Filter тоже странно, если так срабатывает ограничение по стоимости... Вообще есть ощущение, что для NL AntiSemi Join оценка количества строк работает некорректно, он офигенно промахивается в количестве строк на внутренней стороне: ожидается одна, реально - 35000. Почему - непонятно, на внешней стороне он честно ожидает 35т. Думаю, из-за этой оценки он и не делает никаких попыток что-либо с этой веткой сделать полезного.
9 авг 16, 15:23    [19520619]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
автор
Вообще есть ощущение, что для NL AntiSemi Join оценка количества строк работает некорректно, он офигенно промахивается в количестве строк на внутренней стороне: ожидается одна, реально - 35000.

Вы уверены, что правильно посмотрели? Для NL SSMS отображает так, что для достоверной картины нужно умножать Estimated Number of Rows на Estimated Number Of Executions. Plan Explorer например отображает иначе, и на картинке из предыдущего сообщения (там оценочные планы), видно, что оценивается правильно 35000 строк.

Вообще, можно не удивляться, что какие-то оптимизации, которые можно было бы сделать, сервер не делает, это вполне может быть и пробел в функциональности, особенно, если это не является распространенной болезненной точкой.
9 авг 16, 17:03    [19521108]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
iljy
Member

Откуда:
Сообщений: 8711
SomewhereSomehow
автор
Вообще есть ощущение, что для NL AntiSemi Join оценка количества строк работает некорректно, он офигенно промахивается в количестве строк на внутренней стороне: ожидается одна, реально - 35000.

Вы уверены, что правильно посмотрели? Для NL SSMS отображает так, что для достоверной картины нужно умножать Estimated Number of Rows на Estimated Number Of Executions. Plan Explorer например отображает иначе, и на картинке из предыдущего сообщения (там оценочные планы), видно, что оценивается правильно 35000 строк.

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


Да, действительно, не посмотрел на Number of Executions внутреннего элемента. Но тогда тем более странно: сервер предпочитает 35 тысяч раз обратиться к таблице, даже не попытавшись закешировать результат. not in может и не является болезненной точкой (ну по крайней мере не в этом :) ), но вложенные циклы-то сплошь и рядом используются. А для конкретно этого случая вариантов оптимизации можно кучу придумать.
10 авг 16, 08:24    [19523047]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
iljy,

Можете попробовать собрать ваши идеи в кучу, сделать какой-нибудь хороший пример и оформить MS в качестве предложения: https://connect.microsoft.com/SQLServer если предложение будет популярным, глядишь, что-нибудь действительно доделают в этой области.
10 авг 16, 14:07    [19524924]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
iljy
Member

Откуда:
Сообщений: 8711
SomewhereSomehow,

надо попробовать :) спасибо за разъяснение!
10 авг 16, 18:06    [19526146]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
архивариус
Member

Откуда:
Сообщений: 163
просто к теме почему бывает медленнее...

6. “WITH (NOLOCK)” doesn’t actually mean no locking.

At some point in your career, you’re going to start using WITH (NOLOCK) on everything because it gets your query results faster. That’s not necessarily a bad idea, but it can come with some surprising side effects that Kendra discusses in her “There’s Something About Nolock” video. I’m going to focus on one of them here, though.

When you query a table – even WITH (NOLOCK) – you take out a schema stability lock. No one else can change that table or indexes until your query is finished. That doesn’t sound like a big deal until you need to drop an index, but you can’t because people are constantly querying a table, and they think there’s no overhead as long as they use WITH (NOLOCK).

There’s no silver bullet here, but start by reading about SQL Server’s isolation levels – I bet READ COMMITTED SNAPSHOT ISOLATION is an even better choice for your app. It gets you consistent data with less blocking hassles.
11 авг 16, 11:30    [19528419]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
архивариус
Member

Откуда:
Сообщений: 163
ссылка потерялась
https://www.brentozar.com/archive/2013/02/7-things-developers-should-know-about-sql-server/
11 авг 16, 11:31    [19528429]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
o-o
Guest
архивариус
просто к теме почему бывает медленнее...
6. “WITH (NOLOCK)” doesn’t actually mean no locking.
...
When you query a table – even WITH (NOLOCK) – you take out a schema stability lock. No one else can change that table or indexes until your query is finished. That doesn’t sound like a big deal until you need to drop an index, but you can’t because people are constantly querying a table, and they think there’s no overhead as long as they use WITH (NOLOCK).

так вы как бы пишете одно, а пример приводите от другого.
у вас же читатели с NOLOCK совсем не тормозятся, они счастливы.
это кто-то другой, желающий дропнуть индекс, висит и ждет.
---
в этой теме обсуждали как доступ в соответствии с IAM может оказаться менее выгодным,
чем в порядке индекса (обычно как раз наоборот)
но если вам нужен пример, когда зависнет читатель с NOLOCK
и именно на *неполученной блокировке Sch-S*, то мы такое тоже обсуждали, вот ссылка на пример:
select with (nolock) отваливается по timeout'у
11 авг 16, 12:05    [19528646]     Ответить | Цитировать Сообщить модератору
 Re: WITH(NOLOCK) - без него значительно быстрее. Странно.  [new]
MasterZiv
Member

Откуда: Питер
Сообщений: 34697
SergeyPK
iap
пропущено...
Изоляция по-умолчанию настраивается. ЕМНИП.

SergeyPK, задавайте хинт явно, а не просто убирайте его.
И никогда не пишите NOT IN(SELECT ...).
Попадётся в подселекте NULL, - и попадёте.

В курсе. Именно поэтому у нас на проекте сейчас и пересматривают весь этот код, что до нас наваяли.
Там много чиго, что мне не нравится. Но вопрос у меня сейчас больше теоретический. Чисто для моего знания и понимания.



всё просто, ты думаешь, что планы одинаковы, а они разные, поэтому ты не можешь понять, почему разница во времени и io.

они не могут быть одинаковыми, потому что разные уровни изоляции.

также важно, есть у тебя mvcc или нет, включено ли оно.

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

это тебе все знать не нужно, нужно брать планы и статистику io и сравнивать, и все.

главное то не это, а что ты будешь делать после того, как поймешь, почему это происходит.
а делать то в общем и нечего, кроме как убрать NOLOCK, так и убирай сразу...
12 авг 16, 06:50    [19532271]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: 1 2 3      [все]
Все форумы / Microsoft SQL Server Ответить