Подтвердить что ты не робот

Что не так с курсорами?

Разработчики SQL Server считают Курсоры плохими, за исключением некоторых случаев. Они считают, что Cursors не используют механизм SQL оптимально, поскольку он является процедурной конструкцией и побеждает основанную на сетке концепцию РСУБД.

Однако разработчики Oracle, похоже, не рекомендуют использовать Cursors. Сами заявления Oracle DML являются неявными курсорами.

Почему эта разница в подходе? Это из-за того, как эти 2 продукта сделаны, или эти рекомендации относятся к обоим продуктам?

4b9b3361

Ответ 1

Что не так с курсорами, так это то, что их часто злоупотребляют, как в Oracle, так и в MS SQL.

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

Конечно, для сохранения такого набора результатов необходимы некоторые ресурсы: locks, latches, memory, даже disk space.

Чем быстрее эти ресурсы будут освобождены, тем лучше.

Сохранение курсора открыто, как открытие открытой двери холодильника

Вы не делаете это часами без необходимости, но это не значит, что вы никогда не должны открывать холодильник.

Это означает, что:

  • Вы не получаете свои результаты по строкам и суммируете их: вместо этого вы вызываете SQL SUM.
  • Вы не выполняете весь запрос и получаете первые результаты от курсора: вы добавляете условие rownum <= 10 к вашему запросу

и т.д.

Что касается Oracle, обработка ваших курсоров внутри процедуры требует печально известного SQL/PLSQL context switch, который происходит каждый раз, когда вы получаете результат запроса SQL из курсора.

Он включает передачу больших объемов данных между потоками и синхронизацию потоков.

Это одна из самых раздражающих вещей в Oracle.

Одним из менее очевидных последствий этого поведения является то, что триггеры в Oracle следует избегать, если это возможно.

Создание триггера и вызов функции DML равно открытию курсора, который выбирает обновленные строки и вызывает код запуска для каждой строки этого курсора.

Простое существование триггера (даже пустого триггера) может замедлить операцию DML 10 times или более.

Тест script на 10g:

SQL> CREATE TABLE trigger_test (id INT NOT NULL)
  2  /

Table created

Executed in 0,031 seconds
SQL> INSERT
  2  INTO   trigger_test
  3  SELECT level
  4  FROM   dual
  5  CONNECT BY
  6     level <= 1000000
  7  /

1000000 rows inserted

Executed in 1,469 seconds
SQL> COMMIT
  2  /

Commit complete

Executed in 0 seconds
SQL> TRUNCATE TABLE trigger_test
  2  /

Table truncated

Executed in 3 seconds
SQL> CREATE TRIGGER trg_test_ai
  2  AFTER INSERT
  3  ON trigger_test
  4  FOR EACH ROW
  5  BEGIN
  6     NULL;
  7  END;
  8  /

Trigger created

Executed in 0,094 seconds
SQL> INSERT
  2  INTO   trigger_test
  3  SELECT level
  4  FROM   dual
  5  CONNECT BY
  6     level <= 1000000
  7  /

1000000 rows inserted

Executed in 17,578 seconds

1.47 секунд без триггера, 17.57 секунд, когда пустой триггер ничего не делает.

Ответ 2

Из MSDN: реализация курсора

Использование курсора менее эффективно, чем используя набор результатов по умолчанию. В default result set only packet отправлено с клиента на сервер, пакет, содержащий выполнить. При использовании курсора сервера, каждый оператор FETCH должен быть отправлен из клиент к серверу, где он должен быть проанализирован и скомпилирован в план выполнения.

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

Я не Oracle DBA, поэтому я не могу говорить о том, как разные реализации. Тем не менее, с точки зрения программирования, набор операций на основе почти всегда быстрее, чем обработка результатов в курсоре.

Ответ 3

Мне всегда говорили, что курсоры, где зло, но всегда гуру MS SQL Server, из-за плохой производительности. Что касается Oracle PL/SQL Я нашел это высказывание, когда использовать курсоры:

Неиспользование курсоров приводит к повторному анализу. Если переменные связывания не используются, тогда происходит сильное разбор всех операторов SQL. Это на порядок влияет на производительность, и это совершенно нецелесообразно. Используйте курсоры с переменными привязки, которые открывают курсор и выполняют его много раз. Будьте подозрительны к приложениям, генерирующим динамический SQL.

Как курсоры неявно создаются при каждой операции, это не похоже на то, чтобы использовать их при необходимости:)

Помните, что реализация Oracle ближе к Postgres, чем к Sybase (Genesis MS SQL Server), поэтому производительность будет различной для каждого из разных задач. Если вы можете, избегайте суеты настройки производительности в системах, которые могут своп back-end, пойдите для наименее общего знаменателя, если вам нужно работать с обоими./Tangential_topic

Ответ 4

Я уверен, что кто-то может объяснить более подробно, но он в основном сводится к курсорам на SQL-сервере, это SLOW.

Ответ 6

В других ответах правильно указывается проблема производительности с курсорами, но они не упоминают, что SQL и реляционные базы данных лучше всего подходят для операций на основе набора, а курсоры - в основном для итеративных операций. Есть несколько операций (в более широком смысле), которые легче выполнять с помощью курсоров, но при работе с SQL вы всегда должны думать о работе с наборами данных. Курсоры часто используются неправильно, потому что кодер не понял, как выполнить задачу, используя операции с настройками.