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

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

13 голосов
/ 13 апреля 2009

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

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

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

Ответы [ 6 ]

22 голосов
/ 14 апреля 2009

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

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

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

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

Держать курсор открытым - это все равно, что держать дверь холодильника открытой

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

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

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

и т. Д.

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

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

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

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

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

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

Тестовый скрипт на 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 секунд с пустым триггером, ничего не делающим.

14 голосов
/ 13 апреля 2009

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

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

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

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

3 голосов
/ 13 апреля 2009

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

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

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

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

1 голос
/ 13 апреля 2009

Я уверен, что кто-то может объяснить более подробно, но это сводится к тому, что курсоры в SQL-сервере МЕДЛЕННЫ.

0 голосов
/ 14 апреля 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...