Каковы преимущества использования курсора базы данных? - PullRequest
41 голосов
/ 05 октября 2010

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

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

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

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

Ответы [ 5 ]

47 голосов
/ 04 апреля 2012

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

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

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

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

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

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

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

Правило большого пальца:

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

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

НТН

27 голосов
/ 05 октября 2010

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Однако есть исключения:

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

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

3 голосов
/ 05 октября 2010

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

ТамВот несколько ситуаций, в которых это может быть полезно:

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

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

Неизбежно, в Википедии есть больше: http://en.wikipedia.org/wiki/Database_cursor

1 голос
/ 04 апреля 2012

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

1 голос
/ 05 октября 2010

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

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

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