Моя таблица SQL слишком большая: получение данных с помощью разбиения на страницы / сегментации результата? - PullRequest
1 голос
/ 09 января 2012

Это вопрос разработки / алгоритма. Вот схема моего сценария:

  • У меня есть большая таблица (скажем, 5 миллионов строк) данных, которые яПозвоню по номеру Cars
  • Затем у меня есть приложение, которое выполняет SELECT * для этой таблицы Cars , собирая все данные и упаковывая их в одну таблицу.файл (который затем куда-то загружается.)
  • Этот файл данных, сгенерированный моим приложением, представляет собой моментальный снимок, как таблица выглядела в данный момент времени.
  • Таблица Автомобили , однако, время от времени обновляется другим процессом, независимо от того, генерирует ли приложение в настоящее время пакет из таблицы или нет.(Там в настоящее время нет синхронизации.)

Моя проблема :

Эта таблица Автомобили становится слишком большой, чтобы сделать один SELECT * против.Когда мое приложение извлекает все эти данные за один раз, оно быстро переполняет объем памяти для моей машины (скажем, 2 ГБ). Кроме того, простое выполнение цепочек SELECT s с LIMIT или OFFSET не выполняет условие синхронизации: таблица часто обновляетсяи я не могу изменить данные между вызовами SELECT.

То, что я ищу :

Способ вытащить всю эту таблицу из приложения в приложениечья емкость памяти меньше данных, предполагая, что размер данных может приближаться к бесконечности.В частности, как мне добиться эффекта разбиения на страницы / сегментирования для моих SQL-выборок?т.е. совершать повторяющиеся вызовы с номером страницы для получения следующего сегмента данных.Идеальное решение учитывает масштабируемость в размере данных.

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

Любые предложения, которые вы можете дать, будут наиболее полезны.Спасибо!

РЕДАКТИРОВАТЬ: По запросу моя реализация использует C # .NET 4.0 и MSSQL 2008.

РЕДАКТИРОВАТЬ # 2: Это не вопрос команды SQL .Это вопрос, связанный с шаблоном проектирования: какова стратегия выполнения разбивки на страницы с разбивкой на большие таблицы?(Особенно, когда указанная таблица получает постоянные обновления.)

Ответы [ 4 ]

1 голос
/ 09 января 2012

Какую базу данных вы используете?Например, в MySQL следующее выберет 20 строк, начиная с 40-й строки, но это предложение только для mysql (правка: кажется, Postgres также допускает это)

 select * from cars limit 20 offset 40
0 голосов
/ 10 января 2012

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

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

0 голосов
/ 09 января 2012

Посмотрите на этот пост, используя лимит и смещение, чтобы создать постраничные результаты из вашего SQL-запроса.

http://www.petefreitag.com/item/451.cfm

Сначала вам нужно будет:

SELECT * from Cars Limit 10

, а затем

SELECT * from Cars limit 10 offset 10

И так далее. Для этого вам нужно будет определить наилучшую нумерацию страниц.

0 голосов
/ 09 января 2012

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

SELECT * INTO OUTFILE "c:/mydata.csv"
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY "\n"
FROM my_table;

Для оракула будет экспорт, для sqlserver / sybase это будет BCP и т. Д.

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

С точки зрения подкачки, простой вариант - просто использовать предложение limit (если mysql) или equivelent в любых используемых вами rdbms, но это последнее средство:

select * from myTable order by ID LIMIT 0,1000
select * from myTable order by ID LIMIT 1000,1000
select * from myTable order by ID LIMIT 2000,1000
...

Выбирает данные в 1000 кусочках строк.

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