В чем преимущества использования курсора базы данных?

Он основан на вопросе интервью, с которым я столкнулся.

Очень короткое определение может быть

Его можно использовать для управления строками возвращенный запросом.

Помимо использования курсора (точки перечислены здесь на MSDN), у меня есть вопрос, на мой взгляд, что если мы сможем выполнить все операции с использованием запроса или хранимой процедуры (если я не ошибаюсь, как мы можем использовать Transact-SQL для ms-sql), есть ли какая-то конкретная точка, в которой мы должны использовать курсор?

Ответ 1

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

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

  • Курсор может сэкономить ваше время - потому что вам не нужно ждать обработки и загрузки вашего полного набора записей
  • Он сохранит вашу память как на сервере, так и на клиенте, потому что им не нужно выделять большой кусок памяти для результатов.
  • Баланс нагрузки как вашей сети, так и вашего сервера. Работа в режиме "всплеска" обычно более эффективна, но может полностью блокировать ваш сервер и вашу сеть. Такие задержки редко желательны для многопользовательских сред. Потоковая передача оставляет место для других операций.
  • Позволяет выполнять операции над запрошенными таблицами (при определенных условиях), которые не влияют на ваш курсор напрямую. Поэтому, пока вы держите курсор в строке, другие процессы могут читать, обновлять и даже удалять другие строки. Это особенно полезно для очень занятых таблиц, много одновременных операций чтения и записи.

Это приводит нас к некоторым оговоркам:

  • Согласованность. Используя курсор, вы, как правило, не работаете с последовательным снимком данных, а в строке. Таким образом, ваш concurrency/согласованность/изоляция гарантирует, что все данные базы данных (ACID) будут удалены только в одну строку. Обычно вы можете сообщить своей СУБД, какой уровень concurrency вы хотите, но если вы слишком небрежны (блокируете всю таблицу, в которой вы находитесь), вы выбросите большую часть ресурсов на серверной стороне.

    /li >
  • Передача каждой строки сама по себе может быть очень неэффективной, так как у каждого пакета есть накладные расходы на переговоры, которых можно избежать, отправив большие, возможно сжатые, куски данных для каждого пакета. (Нет сервера БД или клиентской библиотеки достаточно глупо, чтобы передавать каждую строку отдельно, там кеширование и разделение на обоих концах, тем не менее, это актуально.)

  • Курсоры труднее делать правильно. Рассмотрим запрос с большим набором результатов, мотивируя вас использовать курсор, который использует предложение GROUP BY с агрегатными функциями. (Такие запросы распространены в хранилищах данных). GROUP BY может полностью уничтожить ваш сервер, поскольку он должен генерировать и хранить весь набор результатов сразу, возможно, даже удерживать блокировки в других таблицах.

Общее правило:

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

"Последовательный характер" означает, что в тяжелых предложениях GROUP BY в вашем запросе нет агрегированных функций. Сервер может лениво решить вычислить 10 строк для вашего курсора, чтобы потреблять из кеша и делать другие вещи тем временем.

НТН

Ответ 2

Курсор - это инструмент, который позволяет вам перебирать записи в наборе. Он имеет концепции порядка и текущей записи.

Как правило, SQL работает с мультимножествами: это наборы, возможно повторяющиеся записи в некотором порядке, взятые в целом.

Скажем, этот запрос:

SELECT  *
FROM    a
JOIN    b
ON      b.a = a.id

работает на мультимножествах a и b.

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

Это позволяет абстрагировать детали реализации и позволить системе попытаться выбрать наилучший возможный алгоритм для запуска этого запроса.

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

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

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

while (!rs.EOF) {
   process(rs);
   rs.moveNext();
}

Этот курсор, который реализует все это для вас.

Это, конечно, касается взаимодействия базы данных и клиента.

Что касается самой базы данных: внутри базы данных вам редко нужны курсоры, поскольку, как я уже сказал выше, почти все преобразования данных могут быть реализованы с использованием операций установки более эффективно.

Однако существуют исключения:

  • Аналитические операции в SQL Server реализованы очень плохо. Например, кумулятивная сумма может быть рассчитана гораздо более эффективно с помощью курсора, чем с использованием операций на основе набора
  • Обработка данных в кусках. Бывают случаи, когда операция, основанная на наборе, должна последовательно применяться к части набора, и результаты каждого блока должны выполняться независимо. Хотя это все еще возможно сделать, используя операции на основе набора, курсор часто является более предпочтительным способом для этого.
  • Рекурсия в системах, которые ее не поддерживают.

Вы также можете прочитать эту статью:

Ответ 3

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

Есть несколько ситуаций, когда это может быть полезно:

  • В тех случаях, когда необходимо имитировать поведение доступа к файлам, например, где реляционная база данных используется в качестве механизма хранения данных для части кода, которая ранее была написана для использования индексированных файлов для хранения данных.

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

Неизбежно, wikipedia имеет больше: http://en.wikipedia.org/wiki/Database_cursor

Ответ 4

С помощью курсора вы получаете доступ к одной строке за раз. Поэтому полезно использовать его, когда вы хотите манипулировать множеством строк, но с одним только в определенный момент времени.

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

Ответ 5

Иногда логика, основанная на множестве, может быть довольно сложной и непрозрачной. В этих случаях, и если производительность не является проблемой, курсор на стороне сервера может быть использован для замены реляционной логики более управляемой и знакомой (неравновесной мыслительной) процедурной логикой, что облегчает обслуживание.