Grails withCriteria提取,或以预定顺序排序的快速方式

时间:2015-08-28 19:10:03

标签: hibernate grails criteria hibernate-criteria

数据库函数返回特定半径内所有事件的id,按其距离排序。

之后,为了保持性能,我急切地在echo "leonardo,davinci" | pcregrep '[^\w\s,]' 加载必要的集合,如下所示:

withCriteria

然而,这会扰乱排序。我注意到这个条件查询的结果返回按id排序的所有事件。这有点有意义,因为 def events = Event.withCriteria { 'in'('id', ids) fetchMode("someRelation", FetchMode.JOIN) // a few more joins setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY) } 不保证任何类型的特殊排序(它也没有任何意义)。然而,这会带来一些问题,因为我希望这个列表是有序的。

所以我做的是:

in

然而,当列表包含~2400个元素时,这段代码会增加大约1秒的总执行时间,这是我希望尽可能降低的。

还有其他方法可以加快这个过程吗?

1 个答案:

答案 0 :(得分:1)

我认为至少有三种方法可以解决您的问题(我已经做了额外的研究和考虑):

SQL方式

根据this gist按字段排序也可以使用Postgres而不仅仅是在mysql中,但它有点棘手,因为它不是直接支持的。正如您在gist讨论中所读到的那样,有不同的方法,但我认为更简洁的是最后一种:通过子句添加自定义订单!

ORDER BY (ID=10, ID=2, ID=56, ID=40) DESC

要在Grails中创建返回具有特定类型的对象的自定义SQL查询,您可以关注this tutorial

Groovy方式(您当前的)

// only four id, for the sake of simplicity
def ids = [10, 2, 56, 40];

// get your events with your criteria
def events = Event.withCriteria {
    'in'('id', ids)
    fetchMode("someRelation", FetchMode.JOIN)
    // a few more joins
    setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY)
}

// create an array that maps event.id -> sortedEventIndex
def indexToIdArray = [];
// event with id 2 is at index 1
// event with id 10 is at index 0 
// ...
// [null, null, 1 , null, null, null, null, null, null, null, 0, ...]
ids.eachWithIndex{ num, idx -> indexToIdArray[$num] = $idx }

def sortedEvents = [];
events.each { ev -> sortedEvents[indexToIdArray[ev.id]] = ev }

通过这种方式,您已经在 O (n)中进行了排序,消耗了一些额外的内存。 我不知道这个解决方案是否真的比你的更好,但是你应该试一试。

另请参阅this interesting article,了解如何在groovy代码中找到性能问题。

客户端方式

使用排序数据将未排序的事件列表返回给客户端,然后在客户端中对它们进行排序。如果您的应用程序的客户端可以以更多方式对事件列表进行排序,我认为此解决方案可能很有用(每个排序操作仅在客户端完成)。

第4,第5 ......

由于这也是一个性能问题,还有其他可能的解决方案(取决于您的域/环境):

  • 急切地缓存一切,甚至是有序的结果
  • 使用固定的点列表进行排序(如果我在p1附近,请使用p1进行排序)
  • 您的想法

我希望这会有所帮助。