2015-05-20 6 views
1

У меня есть внешняя служба, в которой я собираю список элементов и сохраняю локально связь между этими элементами и пользователем. Я передаю эту внешнюю службу имя и возвращаю связанные элементы с этим именем. Я предпочитаю сохранять их локально, потому что я хотел бы сохранить свои собственные атрибуты об этих внешних элементах, как только они были обнаружены моим приложением. Элементы сами по себе являются довольно статическими объектами, но общее их число неизвестно, и единственный раз, когда я узнаю о новых, - это если у нового пользователя есть связь с ними во внешней службе.Проверка наличия набора элементов в базе данных быстро

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

Сейчас у меня есть следующее (псевдокод, так как он разбит на сервисные слои и т.д.):

Set<ExternalItem> items = externalService.getItemsForUser(user.name); 
for (ExternalItem externalItem : items){ 
    Item dbItem = sessionFactory.getCurrentSession().get(Item.class,item.id); 
    if (dbitem == null){ 
     //Not in database, create it. 
     dbItem = mapToItem(externalItem); 
    } 
    user.addItem(dbItem); 

} 
sessionFactory.getCurrentSession().save(user);//Saves the associated Items also. 

время эта операция занимает около 16 секунд в течение приблизительно 500 внешних элементов. Удаленная операция составляет около 1 секунды, и сохранение также незначительно. Утечка, которую я замечаю, связана с многочисленными звонками session.get(Item.class,item.id), которые я делаю.

Есть ли лучший способ проверить существующий элемент в моей базе данных, чем этот, учитывая, что я получаю набор обратно из моей внешней службы?

Примечание: Идентификатор внешнего элемента является надежным, чтобы быть таким же, как у меня, и один идентификатор всегда будет представлять собой один и тот же элемент внешнего

+0

Если вы не хотите добавлять другую структуру данных (фильтр), единственное, что я могу себе представить, это помочь сократить круглые поездки в базу данных (и убедиться, что есть индекс в ItemID). Круговые поездки будут уменьшены за счет использования собственного SQL-запроса с конструкцией IN (id1, id2, id3). К сожалению, я думаю, что это нужно сделать вручную, построив готовые заявления равного размера с несколькими аргументами. (сохраните количество маленьких вариаций). – eckes

+0

@eckes Итак, я предполагаю, что я поместил их в группы по 20 или около того, сделайте собственный выбор, где id (id1, id2, ..., id20), а затем исследуйте возвращенную структуру, для которой возвращаются идентификаторы этого исходного списка , –

+0

Да, таким образом, 110 результатов были бы 15 roundtrips (5 x 20 + 10 x 1) только с двумя различными операторами для синтаксического анализа. Или вы можете иметь 100,10 и 1 в зависимости от диапазона количества элементов, которые обычно проверяются. Я не уверен, что у Hibernate есть помощник для этого. – eckes

ответ

1

Я определенно рекомендовал бы родной запрос, как это рекомендовано в комментариях.

Я бы не стал замочить их, учитывая цифры, о которых вы говорите. Postgres должен иметь возможность обрабатывать предложение IN с 500 элементами без проблем. У меня были запрограммированные сгенерированные запросы со множеством других элементов, кроме тех, которые выполнялись нормально.

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

+0

Я сделал это так, повторяя внешние идентификаторы, добавляя их в набор, а затем запрашивая 'select * из элементов, где id in (...)' и возвращает список идентификаторов, которые совпадают. Затем я снова повторил исходный набор внешних элементов, и для каждого, что было в наборе результатов, я сделал 'session.load()', и для каждого, который не был в наборе результатов, я создал новый и впоследствии сохранил все ,Операция теперь длится 2-3 секунды, что гораздо более разумно для webapp. –

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