Дополнение SQL Server 2012 показывает некоторые улучшения производительности в этой области, но, кажется, не для решения конкретных проблем, отмеченных ниже. Этот должен apparently be fixed в следующей крупной версии после SQL Server 2012!
В вашем плане показаны отдельные вставки с использованием параметризованных процедур (возможно, с автоматическим параметрированием), поэтому время разбора/компиляции для них должно быть минимальным.
Я думал, что я посмотрю на это немного больше, поэтому настроил цикл (script) и попытался настроить количество статей VALUES
и записать время компиляции.
Затем я разделил время компиляции на количество строк, чтобы получить среднее время компиляции за предложение. Результаты приведены ниже
До 250 VALUES
положения не представляют компиляции время/количество статей имеет небольшой восходящий тренд, но ничего слишком драматическое.
Но есть внезапное изменение.
Этот раздел данных показан ниже.
+------+----------------+-------------+---------------+---------------+
| Rows | CachedPlanSize | CompileTime | CompileMemory | Duration/Rows |
+------+----------------+-------------+---------------+---------------+
| 245 | 528 | 41 | 2400 | 0.167346939 |
| 246 | 528 | 40 | 2416 | 0.162601626 |
| 247 | 528 | 38 | 2416 | 0.153846154 |
| 248 | 528 | 39 | 2432 | 0.157258065 |
| 249 | 528 | 39 | 2432 | 0.156626506 |
| 250 | 528 | 40 | 2448 | 0.16 |
| 251 | 400 | 273 | 3488 | 1.087649402 |
| 252 | 400 | 274 | 3496 | 1.087301587 |
| 253 | 400 | 282 | 3520 | 1.114624506 |
| 254 | 408 | 279 | 3544 | 1.098425197 |
| 255 | 408 | 290 | 3552 | 1.137254902 |
+------+----------------+-------------+---------------+---------------+
Кэшированного размер план, который был растет линейно внезапно падает, но CompileTime увеличивается в 7 раз и CompileMemory взмывает вверх. Это точка отсечения между планом, являющимся автоматической параметризованной (с 1000 параметрами), к не параметризованной. После этого он становится линейно менее эффективным (с точки зрения количества предложений стоимости, обработанных за данный момент времени).
Не знаете, почему это должно быть. Предположительно, когда он компилирует план для конкретных значений буквального значения, он должен выполнять некоторую активность, которая не масштабируется линейно (например, сортировка).
Это не влияет на размер кэшированного плана запросов, когда я пробовал запрос, состоящий полностью из повторяющихся строк, и ни один из них не влияет на порядок вывода таблицы констант (и по мере того, как вы вставляете в время, затраченное на кучу, было бы бессмысленным, даже если бы оно это делало).
Кроме того, если кластерный индекс добавляется в таблицу, в плане по-прежнему отображается явный шаг сортировки, поэтому он не сортирует во время компиляции, чтобы избежать сортировки во время выполнения.
Я попытался посмотреть на это в отладчике, но государственные символы для моей версии SQL Server 2008, кажется, не будут доступны так что вместо этого я должен был смотреть на эквивалентном UNION ALL
строительства в SQL Server 2005.
типичный трассировки стека ниже
sqlservr.exe!FastDBCSToUnicode() + 0xac bytes
sqlservr.exe!nls_sqlhilo() + 0x35 bytes
sqlservr.exe!CXVariant::CmpCompareStr() + 0x2b bytes
sqlservr.exe!CXVariantPerformCompare<167,167>::Compare() + 0x18 bytes
sqlservr.exe!CXVariant::CmpCompare() + 0x11f67d bytes
sqlservr.exe!CConstraintItvl::PcnstrItvlUnion() + 0xe2 bytes
sqlservr.exe!CConstraintProp::PcnstrUnion() + 0x35e bytes
sqlservr.exe!CLogOp_BaseSetOp::PcnstrDerive() + 0x11a bytes
sqlservr.exe!CLogOpArg::PcnstrDeriveHandler() + 0x18f bytes
sqlservr.exe!CLogOpArg::DeriveGroupProperties() + 0xa9 bytes
sqlservr.exe!COpArg::DeriveNormalizedGroupProperties() + 0x40 bytes
sqlservr.exe!COptExpr::DeriveGroupProperties() + 0x18a bytes
sqlservr.exe!COptExpr::DeriveGroupProperties() + 0x146 bytes
sqlservr.exe!COptExpr::DeriveGroupProperties() + 0x146 bytes
sqlservr.exe!COptExpr::DeriveGroupProperties() + 0x146 bytes
sqlservr.exe!CQuery::PqoBuild() + 0x3cb bytes
sqlservr.exe!CStmtQuery::InitQuery() + 0x167 bytes
sqlservr.exe!CStmtDML::InitNormal() + 0xf0 bytes
sqlservr.exe!CStmtDML::Init() + 0x1b bytes
sqlservr.exe!CCompPlan::FCompileStep() + 0x176 bytes
sqlservr.exe!CSQLSource::FCompile() + 0x741 bytes
sqlservr.exe!CSQLSource::FCompWrapper() + 0x922be bytes
sqlservr.exe!CSQLSource::Transform() + 0x120431 bytes
sqlservr.exe!CSQLSource::Compile() + 0x2ff bytes
Так происходит от имен в стеке след оказывается тратить много времени сравнения строк.
This KB article указывает на то, что DeriveNormalizedGroupProperties
связано с тем, что раньше называли normalization этап обработки запроса
Этот этап теперь называется обязательным или algebrizing и он принимает выходной вал выражение разбора из предыдущей стадии синтаксического анализа, и выводит (дерево процессоров запросов), чтобы перейти к оптимизации (в этом случае оптимизация тривиального плана) [ref].
Я попробовал еще один эксперимент (Script), который должен был повторить первоначальный тест, но посмотрел на три разных случая.
- Имя и фамилия Строки длиной 10 символов без дубликатов.
- Имя и фамилия Строки длиной 50 символов без дубликатов.
- Имя и фамилия Строки длиной 10 символов со всеми дубликатами.
Это ясно видно, что чем больше струны чем хуже, и что, наоборот, все больше дублируют тем лучше вещи получить. Как уже упоминалось ранее, дубликаты не влияют на размер кеш-плана, поэтому я предполагаю, что при построении дерева алгебраированного выражения должен существовать процесс дублирования идентификации.
Редактировать
Одно места, где заемные средствами этой информации shown by @Lieven here
SELECT *
FROM (VALUES ('Lieven1', 1),
('Lieven2', 2),
('Lieven3', 3))Test (name, ID)
ORDER BY name, 1/ (ID - ID)
Потому что во время компиляции он может определить, что Name
столбца не имеет дубликатов он пропускает заказ вторичного 1/ (ID - ID)
выражения в (сортировка в плане имеет только один столбец ORDER BY
), и ошибка деления на нуль повышается. Если в таблицу добавлены дубликаты, то оператор сортировки показывает два порядка по столбцам, и ожидаемая ошибка повышается.
это не чистые тесты, ничего, исполняемый параллельно , никаких повторных данных (каждый запрос с разными данными, конечно, во избежание простого кеширования) – Borka
есть ли какие-либо триггеры? –
Я преобразовал программу в TVP, чтобы преодолеть предел 1000 значений и получил большой прирост производительности. Я проведу сравнение. – Paparazzi