Как стать автором
Обновить
63
0
Олег @unfilled

Пользователь

Отправить сообщение

Estimate'ы - это ни о чём. Вы же видите, что количество чтений из родного индекса стало даже меньше, чем из ручного на прошлом скрине (ему, видимо, тоже нужен ребилд, т.к. из него читать всё равно должно быть меньше).

Плюс, вы в запросе используете локальную переменную, что тоже может оказывать влияние на estimate, попробуйте этот запрос выполнить через sp_executesql

Новый индекс уже существующего, читать меньше. Условие на равенство бессмысленно, он это знает из статистики. Поле есть в индексе - видимо оно в составе ключа кластерного индекса (или вы включили его в included).

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

Проверьте, кстати, fill factor у обоих индексов, если он ниже у родного индекса - это тоже будет влияние на разницу в чтении.

Предполагаю, что если вы сделаете ребилд индекса, количество чтений практически сравняется. Разница должна быть около 150 тысяч - 5 байт * 210 млн строк / 8192 (размер страницы) - столько сэкономлено за счёт описанных изменений ключа индекса.

А каков процент фрагментации "родного" 1Совского индекса и средняя заполненность страницы? Не могу понять чем может быть вызвана разница в 2 миллиона чтений для индексов, единственное различие между которыми - это 5 байтовая константа в ключе.

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

Покажите, пожалуйста, вывод set statistics io on для обоих запросов.

Кажется, что убрав одно поле из индекса, вы выиграли мегабайт 350 на 70 млн записей - этим не может объясняться разница в скорости выполнения

Что вы имеете в виду под "нижние ветки индекса"? В любом случае он будет опускаться на листовой уровень, т.к. только оттуда можно получить данные, которые нужно вывести.

В частности было отмечено, что без дополнительных условий в Index seek, в поток для Megre join попадают все записи индекса и приходится указывать дополнительные фильтры для ограничения. Вопрос: почему так происходит? - остался открытым.

Пропустил тот пост, сейчас прочитал - и так происходит потому что так работает merge join. Помогите ему, вместо фильтра по дате фильтр по ИдИсхСистемы >= (выбрать мин(СвязаннаяОпИдИсхСистемы) из Врем_...), если 1С так может (не помню уже). С вашим новым индексом, да и со старым тоже - это должно работать не хуже фильтра по дате

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

Разница в скорости выполнения тоже кажется вызванной банальным кешированием.

Второй подход заключается в использовании динамического SQL:

А почему не использовать sp_executesql? Проблему с SQL Injection он по крайней мере решит.

Ага, именно поэтому на следующий день устраивает скандал из-за того, что видит, что он компьютер к сети подключил

 В отместку он взламывает школьную систему и переделывает расписание так, чтоб оказаться в одном классе с Кейт.

Не смог пройти мимо. В отместку он всё-таки взламывает школьную систему и вызывает "протечку бассейна", а в класс с ней записывается для собственного удовольствия

Я правильно понимаю, что раз статья опубликована человеком с подписью "редактор Хабра" - то теперь это тематика Хабра, а не какого-нибудь VC или Пикабу?

Логика не двоичная используется с null.

В else "идёт" то, что не true. unknown - не true, поэтому попадает в else.

Если не знаешь, что операции сравнения с null возвращают unknown, который не true, и не false, то да, сплошное удивление.

Спасибо за статью! Не пользуюсь SQLite, но про внутренности БД всегда интересно читать)

Засовывать varchar(max) в included-колонки индекса - так себе практика.

Согласен, вроде и не утверждал обратного, хотя иногда и приходится.

Computed колонки лучше делать persisted

Можете пояснить - зачем persisted? Зачем хранить и в кластерном индексе, и в самом индексе, если они мне особо и не нужны, а только для оптимизации запроса?

computed persisted-колонку LEFT(x, 200) и индекс по ней - если реально данные не длиннее 200 символов.

Зависит от того, какая средняя длина. Я предпочитаю объявлять больше, чтобы не было спилов в tempdb, если в выборке будут слишком длинные varchar'ы.

DROP INDEX ix_ON ON smth (field2_calculated);
GO
ALTER TABLE smth
    DROP COLUMN field2_calculated;
GO
ALTER TABLE smth
    ADD field2_calculated AS  LEFT(field2, 200) PERSISTED;
GO
CREATE INDEX ix_ON ON smth (field2_calculated);
GO

Msg 1919, Level 16, State 1, Line 18 Column 'field2_calculated' in table 'smth' is of a type that is invalid for use as a key column in an index.

Явно приводить тип всё равно нужно.

Не забывайте ещё, что varchar(max) хранятся в куче

зависит от реальной длины строки

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

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

Более того, MS, оказывается, переписали свой whitepapper по перестройке индексов и там прямо пишут, что зачастую положительный эффект, наблюдаемый после ребилда - это следствие обновления статистики, а не ребилда как такого.

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

Так может лучше вообще не трогать индексы на таких системах? Не насиловать регулярно диски, а лучше почаще выполнять checkdb?

Ну, т.е. пост же как раз об этом - перестройка индексов стандартными средствами может дать какой-то минимальный прирост производительности (если он вообще будет), но потребует кучу ресурсов, сгенерирует тонну логов, инвалидирует кучу планов и может вызвать блокировки (на не-Enterpise редакции).

В вашем примере как раз только процент заполненности страницы и может сыграть какую-то роль. Памяти же фрагментированные индексы, заполненные на 100 процентов будут занимать столько же, сколько и совсем не фрагментированные.

Не совсем понял, что имеется в виду. Оверинжениринг - это обслуживать индексы в принципе? Или оверинжениринг - это не использовать стандартные планы обслуживания?

Информация

В рейтинге
5 994-й
Откуда
Омск, Омская обл., Россия
Дата рождения
Зарегистрирован
Активность