Почему реляционные запросы на основе наборов лучше, чем курсоры?

Запросы на основе множества language-independent (обычно) быстрее, потому sql-select что:

  1. У них есть больше информации для оптимизатора запросов
  2. Они могут выполнять пакетное чтение с диска
  3. Требуется меньше журналов для откатов, журналов транзакций и т. д.
  4. Берется меньше блокировок, что снижает накладные расходы
  5. Логика, основанная на наборах, находится в центре внимания РСУБД, поэтому они были сильно оптимизированы для нее (часто за счет процедурной производительности)

Перенос данных на промежуточный sql-statement уровень для их обработки sql-query может быть полезен, поскольку sqlselect он снимает нагрузку с сервера sqlselect БД (который труднее всего sql-query масштабировать, и обычно sql-select он выполняет и другие задачи). Кроме sql-select того, у вас обычно нет таких sql-syntax же накладных расходов (или sql-syntax преимуществ) на среднем уровне. Такие sql вещи, как журналирование select-statement транзакций, встроенная блокировка sqlselect и блокировка и т. д. — иногда sql-syntax они необходимы и полезны, а sqlselect иногда — просто пустая трата sql-query ресурсов.

Простой курсор с select-statement процедурной логикой по сравнению select-statement с примером на основе набора sql-statement (T-SQL), который будет назначать sqlselect код города на основе телефонной language-agnostic станции:

--Cursor
DECLARE @phoneNumber char(7)
DECLARE c CURSOR LOCAL FAST_FORWARD FOR
   SELECT PhoneNumber FROM Customer WHERE AreaCode IS NULL
OPEN c
FETCH NEXT FROM c INTO @phoneNumber
WHILE @@FETCH_STATUS = 0 BEGIN
   DECLARE @exchange char(3), @areaCode char(3)
   SELECT @exchange = LEFT(@phoneNumber, 3)

   SELECT @areaCode = AreaCode 
   FROM AreaCode_Exchange 
   WHERE Exchange = @exchange

   IF @areaCode IS NOT NULL BEGIN
       UPDATE Customer SET AreaCode = @areaCode
       WHERE CURRENT OF c
   END
   FETCH NEXT FROM c INTO @phoneNumber
END
CLOSE c
DEALLOCATE c
END

--Set
UPDATE Customer SET
    AreaCode = AreaCode_Exchange.AreaCode
FROM Customer
JOIN AreaCode_Exchange ON
    LEFT(Customer.PhoneNumber, 3) = AreaCode_Exchange.Exchange
WHERE
    Customer.AreaCode IS NULL

sql

language-agnostic

cursor

2022-06-13T14:12:32+00:00