2013-01-16 2 views
14

Я хочу, чтобы иметь возможность извлекать все записи из очень большой таблицы с помощью Slick. Если я попытаюсь сделать это через foreach, для или списка выборки; Я получаю исключение из памяти.Scala Slick Lazy Fetch

Есть ли способ использовать «курсоры» с Slick или ленивой загрузкой, которые только при необходимости извлекают объект, уменьшая объем используемой памяти?

+0

Не знаете, почему foreach приведет к OOM, он должен действовать только по одному элементу за раз. Вместо этого вы можете попробовать элементы(), которые возвратят CloseableIterator. Если это также приводит к OOM, разместите остальную часть кода. – Saish

+1

Любые обновления по этому вопросу? – S0rin

ответ

6

Не уверен, что вы имеете в виду курсоров, но вы можете получить частичные данные, используя нумерацию страниц:

query.drop(0).take(1000) will take the first 1000 records 

query.drop(1000).take(1000) will take from 1001 to 2000 lines of the table. 

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

+1

Да, я думал, что я хочу что-то вроде 'fetchNext' просто для того, чтобы захватить следующую запись в наборе результатов. Кажется, что 'foreach' извлекает все результаты в список (заканчивается память в процессе). Возможно, я смогу реализовать свою собственную функцию для извлечения части набора результатов с использованием техники разбиения на страницы. THANKS –

+0

Почему бы не использовать пятно [итератор] (http://slick.typesafe.com/doc/1.0.1/api/index.html#scala.slick.util.CloseableIterator)? – matanster

+0

@matt Когда-то в прошлом позиционируемый итератор вызывал ошибку outofmemory, но я думаю, что этот вопрос был решен. У Iterator также есть методы take and drop, но я думаю, что вы имеете в виду использование следующего и hasnext-методов, не так ли? – dirceusemighini

1

вы можете использовать комбинацию iterator, которая возвращает итератор:

val object = Objects.where(...).map(w => w).iterator() 

и GroupBy:

val chunkSize = 1000 
val groupedObjects = objects.grouped(chunkSize) 
groupedObjects.foreach {objects => objects.par.map(h => doJob(h))} 

, как предполагают, в ответ этой answer

+0

вы пропустили s в конце определения объектов val – dirceusemighini

0

dirceusemighini является правильным. Я столкнулся с аналогичной проблемой несколько дней назад из-за неправильного предположения о Query.list(), поэтому я могу дать еще несколько контекстов. Из справки Slick:

«Запросы выполняются с использованием методов, определенных в типе Invoker (или UnitInvoker для безпараметрических версий). Существует неявное преобразование из Query, поэтому вы можете выполнить любой запрос напрямую. чтение полного набора результатов в строгую коллекцию со специальным методом, таким как список или общий метод, с помощью которого можно построить любую коллекцию »

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

Смежные вопросы