Линк это курсор? - PullRequest
       17

Линк это курсор?

2 голосов
/ 14 декабря 2008

Я знаком с .NET и с SQL. Теперь я смотрю на новый LINQ, и он выглядит как курсор. Я понимаю простоту использования и т. Д., Но если я выполняю запрос LINQ-to-SQL с циклом foreach, я просто использую курсор БД? Или есть какая-то магия за кулисами, когда LINQ собирает все данные одновременно и передает их в мою программу по одной строке за раз?

Ответы [ 3 ]

9 голосов
/ 14 декабря 2008

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

3 голосов
/ 14 декабря 2008

LINQ имеет много воплощений. Поскольку вы упоминаете LINQ-to-SQL, я сосредоточусь на этом: он ни то, ни другое ... он наиболее сопоставим с IDataReader - то есть он выполняет построенную команду TSQL, а затем возвращает обработанные записи построчно (см. ниже), как он получает их от SQL Server. Как и в случае IDataReader, вы получаете только один шанс на строку, если только вы не буферизируете данные, используя .ToArray(), .ToList() и т. Д.

Выполненная команда TSQL построена на основе созданного вами запроса LINQ и параметризована для предотвращения внедрения SQL - поэтому если вы используете «где», выполняемый TSQL включает «WHERE» и т. Д.

В действительности, клиент потребляет записи по требованию через IEnumerable[<T>], поэтому для обработки входящего потока TDS должен быть небольшой буфер, но он не совпадает с курсором базы данных.

Обратите внимание, что большинство операций (сортировка и т. Д.) Могут быть отправлены на сервер и переведены на TSQL - но возможно, что некоторые действия необходимо выполнить на клиенте, что может снова заставить его буферизовать больше данных в памяти , Это особенно верно, если вы заставите его через .ToEnumerable(), который переключается на LINQ-to-Objects. Если LINQ-to-Objects выполняет операцию буферизации (сортировку, группировку и т. Д.), То ему потребуется загрузить данные в память.

Здесь следует отметить несколько вещей; например, если вы хотите вычислить полностью отдельные агрегаты и т. д. в запросе, вы должны (обычно) выполнить его дважды (и т. д.) или поместить его в буфер (не обязательно для больших данных). Для этого типа сценария (и других) Джон Скит и я написали альтернативную реализацию LINQ, которая работает как push , а не pull , позволяя передавать данные через несколько параллельных процессов. однажды. Джон объясняет это лучше здесь . Этот тип вещей в основном используется, если у вас есть очень большой, однократный поток данных, для которого вы хотите выполнить сложную обработку. Интересно, хотя.

1 голос
/ 14 декабря 2008

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

Это неявный курсор, который управляется сервером базы данных, но он все еще является курсором.

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

Когда вы запускаете запрос DLINQ, код LINQ преобразуется в массовый запрос SQL, который отправляется в базу данных с использованием ADO.NET аналогично тому, что вы написали бы, если бы вы генерировали строки запроса и отправляли их. в базу данных.

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

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