Форум программистов, компьютерный форум, киберфорум
C#: Базы данных
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 5.00/26: Рейтинг темы: голосов - 26, средняя оценка - 5.00
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590

Как можно читать данные порциями?

23.02.2021, 17:45. Показов 5114. Ответов 34
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Привет!

Хотелось бы разобраться со следующим вопросом. Есть у нас какая-то БД. Есть там какая-то большая таблица, которую надо вычитать приложению, и выполнить какую-то обработку над каждой записью. Запрос на выборку выглядит так:

SQL
1
SELECT id, description FROM test_table
Таблица эта очень большая и вычитать её полностью в память, например, не представляется возможным.

Что бы я хотел: что бы запрос остался таким же, как есть, а я как-то просто дал серверу (или драйверу?) указание: давай ка мне поэтому запросу 1000 записей, теперь давай следующую 1000, теперь еще 1000 и т.п. В коде на примере MS SQL-я это могло бы выглядеть так:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
using (SqlConnection connection = new SqlConnection(_connectionString))
{
    connection.Open();
    SqlCommand command = new SqlCommand("SELECT id, description FROM test_table", connection);
    SqlDataReader reader = command.ExecuteReader();
 
    while (reader.HasNext(1000))
    {
        while (reader.Read())
        {
            ...
        }
    }
}
Можно ли что-то такое сделать?
Или же кроме как разбить запрос на какие-то подзапросы, которые бы возвращали меньше данных чем выборка всей таблицы, ничего не сделаешь?
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
23.02.2021, 17:45
Ответы с готовыми решениями:

Как подгружать данные порциями в ItemsRepeater?
Статья про ItemsRepeater. Даже нашёл XamlDataVirtualization. Там пример мне не подходит. Мне просто нужно, чтобы скролл или сам...

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

Можно ли читать данные программой на Java из файлов Excel?
Можно ли читать данные программой на Java из файлов Exel?

34
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
24.02.2021, 15:37  [ТС]
Студворк — интернет-сервис помощи студентам
Рядовой, у меня вопрос в том, как это на уровне своего приложения можно сделать.
0
Эксперт .NET
 Аватар для Usaga
14367 / 9468 / 1360
Регистрация: 21.01.2016
Сообщений: 35,721
24.02.2021, 16:17
Цитата Сообщение от V0fka Посмотреть сообщение
Отсюда я делаю вывод, что DataReader таки выгребает все данные.
Это не SqlDataReader все данные выгребает, а вы:

C#
1
rows.Add(row);
Что тут происходит по вашему?)
0
800 / 583 / 207
Регистрация: 21.02.2019
Сообщений: 2,095
24.02.2021, 16:54
V0fka,
.. ну, если уж костылить, то можно, например (если есть автоинкрементное поле - если нет, добавить) вытаскивать через SELECT TOP 1000 WHERE autoId > offset, где offset , будет последний autoID в порции .. По сути это то же самое, но может будет быстрее .. А может, и не будет ..
0
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
24.02.2021, 17:13  [ТС]
Цитата Сообщение от Usaga Посмотреть сообщение
Это не SqlDataReader все данные выгребает
Как же не DataReader, если я после строки
C#
1
SqlDataReader reader = command.ExecuteReader();
выключаю SQL сервер и у меня нормально дальше выполняется метод? А
C#
1
rows.Add(row);
нормально отрабатывает с уже выключенным SQL сервером.

carrotik, вопрос именно в том как бы не костылить
0
800 / 583 / 207
Регистрация: 21.02.2019
Сообщений: 2,095
24.02.2021, 18:03
Цитата Сообщение от V0fka Посмотреть сообщение
вопрос именно в том как бы не костылить
.. перенос базы с сервера на сервер (причем, иной платформы) - это не задача, решаемая прикладным приложением на c# , а работа по обслуживанию БД инструментами самой БД (ее движка), т.е. скриптами ... Ваш подход - именно костыль, а тут уж как пойдёт ...
0
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
24.02.2021, 20:27  [ТС]
Цитата Сообщение от carrotik Посмотреть сообщение
.. перенос базы с сервера на сервер (причем, иной платформы)
Я же не говорил вроде нигде, что у меня задача состоит в том, что бы перенести откуда-то куда-то базу. Я может привел это как пример, но вопрос совсем не в этом. Вопрос о подходе, как такое можно сделать на уровне своего приложения.
0
1497 / 1238 / 245
Регистрация: 04.04.2011
Сообщений: 4,363
24.02.2021, 23:54
Цитата Сообщение от V0fka Посмотреть сообщение
как такое можно сделать на уровне своего приложения.
Вам уже говорили, что способов множество. Причем все "клиентские", т.е. на уровне именно приложения (существуют еще и серверные, когда "нарезка" происходит на SQL-сервере с помощью UDF или SP, но о них речь не идет).

Способы можно разделить на 3 типа:

1. Низкий уровень (ADO.NET). С помощью SQL-предикатов offset-fetch https://info-comp.ru/obuchenie... t-sql.html составляется нативный запрос SELECT. Отслеживание порций (страниц) - логикой приложения (листание).

2. Уровень Linq с использованием репозитория и моделей. Логика в алгоритмах имплементации (методах репозитория)

3. Высокий уровень - использование ORM, в общих чертах описанный здесь Usaga

Добавлено через 2 минуты
Однако так и не смог понять серьезных причин для тягания на клиента 1 млн записей, пусть даже небольшими порциями
0
Эксперт .NET
 Аватар для Usaga
14367 / 9468 / 1360
Регистрация: 21.01.2016
Сообщений: 35,721
25.02.2021, 07:35
Цитата Сообщение от V0fka Посмотреть сообщение
выключаю SQL сервер и у меня нормально дальше выполняется метод? А
В документации чётко сказано:

To retrieve data using a DataReader, create an instance of the Command object, and then create a DataReader by calling Command.ExecuteReader to retrieve rows from a data source. The DataReader provides an unbuffered stream of data that allows procedural logic to efficiently process results from a data source sequentially. The DataReader is a good choice when you're retrieving large amounts of data because the data is not cached in memory.
Это значит, что какой-то небольшой буфферишко быть может, что на стороне SQL Server'а, что на стороне клиента, в ADO.NET. Но вся выборка в оперативку не выгребается, ибо это бред.
0
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
26.02.2021, 16:12  [ТС]
Usaga, я провел эксперимент со 100 000 строк. Событие SQL:BatchCompleted возникает в момент выполнения строки кода
C#
1
SqlDataReader reader = command.ExecuteReader();
Если я после этой строки останавливаю SQL сервер, то примерно на ~60 000-й итерации приложение выпадает на строке
C#
1
reader.GetInt64(0)
То есть подтверждается то, что SqlDataReader действительно не читает все сразу.

Теперь я быхотел понять как это может быть реализовано? Интересен принцип, концепция, а не конкретная реализация.

Как я себе это представляю. В момент SqlDataReader reader = command.ExecuteReader(); через сокет на сервер отправляется запрос. Сервер выполняет запрос, помещает себе данные в tempdb и отправляет какую-то порцию данных в сокет, откуда пришел этот запрос и в конце какое-то сообщение "конец порции" (если отправил не все данные). При этом СКЛ как-то запоминает что конкретно уже отправил в клиентский сокет и слушает его дальше. Клиент читает сокет до момента пока не придет какое-то сообщение типа "конец порции", кладет себе данные в какой-то буфер и запоминает, что это не конец данных, а конец порции. Когда буфер дочитывается кем-то, он отправляет в тот же открытый сокет сообщение типа "давай следующую порцию" и СКЛ сервер отправляет ему очередную порцию. Если СКЛ сервер все данные отправил в сокет, он посылает какое-то сообщение, типа "закончили", разрывает подключение и чистит tempdb.

Или это как-то проще делается?
0
800 / 583 / 207
Регистрация: 21.02.2019
Сообщений: 2,095
26.02.2021, 16:17
V0fka,
..а вы попробуйте выдернуть сетевой шнур (витую пару, не силовой), тогда будет более понятно, а где, собственно, буфер - на сервере, или на клиенте ... Если вы останавливаете службу MSSQL Server, то это не означает, что поток данных сразу разрывается ...
0
 Аватар для Cupko
658 / 595 / 171
Регистрация: 17.07.2012
Сообщений: 1,682
Записей в блоге: 1
26.02.2021, 17:38
Лучший ответ Сообщение было отмечено V0fka как решение

Решение

When a request is submitted for execution, SQL Server sends result sets back to clients in the following way:

SQL Server receives a network packet from the client containing the Transact-SQL statement or batch of Transact-SQL statements to be executed.

SQL Server compiles and executes the statement or batch.

SQL Server begins putting the rows of the result set, or multiple result sets from a batch or stored procedure, in network packets and sending them to the client. SQL Server puts as many result set rows as possible in each packet.

The packets containing the result set rows are cached in the network buffers of the client. As the client application fetches the rows, the ODBC driver or the OLE DB provider pulls the rows from the network buffers and transfers the data to the client application. The client retrieves the results one row at a time in a forward direction.

This mode of returning results is known as a default result set.
A default result set is not given to an application in one large block. The result set is cached in the network buffers on the client. The application fetches through the result set one row at a time. On each fetch, the OLE DB provider or the ODBC driver moves the data from the next row in the network buffer into variables in the application.
https://docs.microsoft.com/en-... dfrom=MSDN
1
1497 / 1238 / 245
Регистрация: 04.04.2011
Сообщений: 4,363
26.02.2021, 18:01
Цитата Сообщение от V0fka Посмотреть сообщение
Когда буфер дочитывается кем-то, он отправляет в тот же открытый сокет сообщение типа "давай следующую порцию" и СКЛ сервер отправляет ему очередную порцию.
1 млн клиентов посылают серверу запрос на извлечение. Тот для каждого что-то выбирает и отправляет "первую порцию". И "слушает" каждого на предмет "а надо ли посылать следующую".

Ага. Именно так все и происходит. Машинист электровоза ни фига не нажмет на "газ" пока лично не спросит у каждого пассажира всех 22 вагонов, а также у их провожающих, готовы ли они ехать

Добавлено через 11 минут
Клиенту по большому счету по барабану, как там сервер что-то кэширует и кэширует ли вообще.
Он должен лишь знать, что пересылка больших объемов данных непременно коснется производительности его самого. Поэтому и не рекомендуется (а в "правильных" софтверных конторах прямо запрещается) гонять тысячи строк, которые ни одному юзеру (человеку) просто не осилить.

Например, есть отчет. Сложный. Состоящий из десятков шагов с выборками из кучи таблиц, группировкой, подсчетами агрегатов, итоговой сортировкой.
Есть два пути:
1. Все эти шаги организовать на Клиенте. Все 101. Выполняя их последовательно - один-за-другим. И в итоге получить некоторую таблицу, которую и загнать в готовый отчет.
2. Весь алгоритм "поручить" серверу, завернув его в SP, и по исполнении получить результирующий датасет, который и уложится в отчет.

Вопрос: Какой путь верный ибо несет минимальные издержки на обоих концах, дает 100% достоверный результат, шустрый и не требует километров кода в приложении ?
0
Эксперт .NET
 Аватар для Usaga
14367 / 9468 / 1360
Регистрация: 21.01.2016
Сообщений: 35,721
27.02.2021, 06:29
Цитата Сообщение от V0fka Посмотреть сообщение
Сервер выполняет запрос, помещает себе данные в tempdb
Ещё чего. Это системная база под временные объекты. Выборка таким объектом не является.
0
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
04.03.2021, 14:19  [ТС]
Коллеги, всем спасибо за ответы!
То что меня интересовало, наверное, описал Cupko в своем посте. То есть все это "порционное" чтение происходит на сетевом уровне.

Как я понял. SQL сервер выполняет запрос и просто выплевывает результат в сокет. Дальше эти данные уже как-то буферизируются на каком-то низком уровне (на уровне ОС?) и операционная система заботится об их отправке. Клиент начинает читать из сокета в свой буфер. По мере чтения буфер сервера освобождается. Как-то так или я опять не туда?
0
1497 / 1238 / 245
Регистрация: 04.04.2011
Сообщений: 4,363
04.03.2021, 15:56
Цитата Сообщение от V0fka Посмотреть сообщение
Клиент начинает читать из сокета в свой буфер
Если под "клиентом" понимать клиентский ПК со всем ПО (ОС+драйверы DAC+ADO.NET+приложение), то да, из "сокета".

Добавлено через 1 минуту
Цитата Сообщение от V0fka Посмотреть сообщение
По мере чтения буфер сервера освобождается. Как-то так или я опять не туда?
Не туда
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
04.03.2021, 15:56

Брать данные из коллекции порциями
Всем привет! Есть коллекция ArrayList<Person>. Person состоит из полей name и isWorked(boolean). В коллекции, например, тысяча...

Как в VBA записать данные в реестр и читать данные из реестра?
Как в VBA записать данные в реестр и читать данные из реестра office xp

Как из VB читать данные с реестра?
Kak iz VB mozhno chitat` dannye is reestra??? Esli mozhno, to dajte primer, a to vchera 3 chasa v i-net'e sidel, da tak normal`nogo...

как читать данные из dbgrid
Есть база данных подключенная к билдеру, как читать данные из dbgrid, чтобы перевести их в listbox?

Как получать/читать данные с COM порта
void MainWindow::Slot_Receive_Data()// ПРИНЯТИЕ { QByteArray infomation; infomation = thisPort.readAll(); while...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
35
Ответ Создать тему
Новые блоги и статьи
Эксперимент с картинкой-обложкой на CodinGame
Adler 10.07.2026
Решил на днях провести эксперимент. У меня есть аккаунт на CodinGame, ТОП-3 по РФ среди 2200 участников (в разделе соревнования по программированию ИИ-ботов). Там есть обложка, куда можно влепить. . .
После бана на Пикабу не работает авторизация аккаунта с Яндекса.
Hrethgir 09.07.2026
В частности https:/ / auto. ru/ logbook/ zapret-na-vozhdenie-posle-65-let_1cf28789-07b4-4c75-a2f7-4cd4edf9deeb тут хотел оставить комментарий такой Зрите в корень - монополизация на разработку программ. . .
GitDOS: Когда я решил скрестить MS-DOS, GitHub и Claude
MaGz GoLd 08.07.2026
Привет, Киберфорум! Хочу поделиться своим проектом, который, надеюсь, вас заинтересует. GitDOS — это веб-приложение, которое позволяет запускать DOS в браузере с тремя крутыми фичами: диски живут в. . .
Учебный мини "цифровой двойник" = (Сервер = Java + Flask_питон )+(3D = Гугловскаая 4T nvideo + google colab) +( WMS = Odoo на Docker)
anaschu 07.07.2026
Увидел в требованиях к вакансии создателя имитационных моделей связку (REst + Api + WMS + Anylogic + питон + 3D Nvideo), и решил посмотреть, что это такое. Из этого всего я работал более менее. . .
Море в объективе
kumehtar 06.07.2026
Хотел написать много проникновенных слов, но передумал. Оно само - говорит. Кто слышит тот слышит.
Doom для терминала без стрельбы и монстров. 3D Raycasting на ascii.
dcc0 05.07.2026
Попросил нейронную сеть deepai. org написать рейкастинг 3D с библиотекой ncurses для Linux. Чтобы можно было ходить на стрелочки. Чтобы стены были отрисованы символами. Справилась. Первый вариант. . .
Установка статуса документа по условию
Maks 05.07.2026
Алгоритм из решения ниже реализован на нетиповом документе "НарядПутевка" разработанного в КА2. Задача: в табличной части "Материалы" документа при записи автоматически устанавливать статус. . .
Сезонность и суточность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет. Но обычно это 50 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru