0

Задача: Мы запрашиваем нашу базу данных с большим количеством записей. Общая производительность приложений в порядке. Но я думаю, что было бы лучше, если бы наше узкое место, обращаясь к специальной таблице, могло быть сделано параллельно.Дизайн шаблонов Grails для параллельных запросов с использованием динамических искателей

Мы используем для этого динамических искателей как:

Object.findAllByObjectCollectionAndParentIsNullAndDeletedByUserIsNull(objectCollection, [sort: 'attr1.number', fetch: [objectType: 'eager']]) 

Я думаю, что об этом решении: Деление запроса в 2 этапа.

  1. Первый шаг загружает только идентификаторы отсортированным способом.
  2. Второй этап (может выполняться в параллельных потоках) загружает объекты по идентификатору и вставляет его в набор результатов.

Я уже искал некоторые намеки на это, но ничего не нашел.

  1. Возможно ли, что это не имеет никакого смысла?
  2. Или уже существует подходящее решение в стандарте/расширениях grails?
  3. Если это имеет смысл, и нет решения: может ли кто-нибудь дать мне подсказку, реализующую его? Но нам нужны идентификаторы в этом порядке, объясненные в примере.

Мы используем grails 2.3.11, hibernate: 3.6.10.13 с jdk 1.7 под ним.

+1

Вы зарегистрировали SQL своего запроса findAll и попытались проанализировать, что он делает? есть ли индексы для родителя и удалены? в противном случае есть только один способ узнать о таких вещах: попробуйте и сравните его. когда дело доходит до производительности, часто нет серебряной пули для всех случаев. – cfrick

+0

Да, конечно. Эти объекты, которые мы загружаем, содержат очень маленькие элементы данных, такие как ячейка листа excel. Поэтому, когда страница отображается, нам нужно много их. – Mirko

ответ

0

Я нашел решение!

ArrayList<Long> objectIds = Attribute.executeQuery("select o.id from Object o, ObjectType ot where o.objectCollection = :oc and o.parent is null and o.deletedByUser is null and oc.typeUsage = ot order by ot.nr asc", [oc: objectCollection]) 
Object[] tmp = new Object[objectIds.size()] 
     withPool(10, { 
      objectIds.eachWithIndexParallel { 
       Long objectId, i -> 
        Object o = Object.findById(objectId, [cache: true]) 
        tmp[i] = a 
      } 
     }) 
     for (Object a : tmp) 
      a.merge() 

Его круглый примерно в 3 раза медленнее!

Я думаю, что причина в том, что

  1. мы должны создать темы и databaseconnections тоже.
  2. После загрузки объектов их необходимо объединить в наш локальный поток.

Но в конце - мы не можем его использовать, потому что ленивые загруженные поля не могут быть загружены по запросу позже. Таким образом, это может быть только решение для объектов только для чтения.