Какие критерии использует SQL Server при выборе одного подхода вместо другого?
Это прежде всего решение, основанное на затратах. Цитата из статьи, на которую вы ссылались, «В ситуациях, когда динамический план выглядит многообещающим, сравнение затрат может быть эвристически пропущено. Это происходит в основном для чрезвычайно дешевых запросов, хотя детали эзотеричны».
Буду ли я прав, думая, что первый метод (без шага заполнения дополнительного рабочего стола) более эффективен?
Это зависит. Динамические и статические планы курсоров имеют разные сильные и слабые стороны. Если в конечном итоге будут затронуты все строки, статический план, вероятно, будет работать лучше. Подробнее об этом чуть позже.
Понятно, что конструкция TOP
не поддерживается для динамических курсоров
Это правда. Все итераторы в плане динамического курсора должны иметь возможность сохранять и восстанавливать состояние, сканировать вперед и назад, обрабатывать одну входную строку для каждой выходной строки и быть неблокирующими. Верх, в общем, не удовлетворяет всем этим требованиям; класс CQScanTopNew
не реализует необходимые методы Set/Get/Goto/Marker()
и ReverseDirection()
(среди прочих).
Я также читал, что динамические курсоры, как правило, медленнее, чем их статические аналоги.
Это часто верно для курсоров Transact-SQL, где затрагивается большая часть или весь набор курсоров. С сохранением и восстановлением состояния динамического плана запросов связаны затраты. Если при каждом вызове обрабатывается одна строка, а все строки в конце концов затрагиваются, это увеличивает затраты на сохранение / восстановление.
Статические курсоры накладывают издержки на создание копии набора (который может быть доминирующим фактором для большого набора), но стоимость извлечения для каждой строки довольно мала. Наборы ключей имеют более высокие издержки на поиск в строке, чем статические, поскольку они должны внешне присоединяться к исходным таблицам для получения неключевых столбцов.
Динамические курсоры оптимальны, когда к относительно небольшой части набора обращаются, и / или поиск не является строкой за раз. Это типичный шаблон доступа во многих распространенных сценариях курсора, только те, которые не тестируются в блогах:)
Если кто-нибудь может объяснить, почему каждое сканирование в первом запросе считается за 2 логических чтения, что также может быть очень полезным
Это относится к тому, как сохраняется состояние сканирования и как считываются показания.
В статье, на которую я ссылался ранее, упоминается, что динамические курсоры используют маркеры. Кто-нибудь может объяснить, что это? Это просто RID или CI, или что-то другое?
Для динамического плана курсора существуют маркеры для каждого итератора, а не только методы доступа. «Маркер» - это вся информация о состоянии, необходимая для перезапуска итератора плана в том месте, где он остановился. Для метода доступа большая часть этого - RID или индексный ключ (при необходимости, с помощью унивификатора), но никак не вся история.