user1698253
user1698253

Reputation: 55

Optimize Grails Queries

I'm trying to optimize the speed in my grails app. I have this:

Catalog a= Catalog.findByName('a');
Element b= Element.findByCatalogAndNumber(a,2);

This way i can find b.

But I'm thinking I could use something like this:

Element b= Element.createCriteria().get{
       catalog{
          eq("name",'a')
       }
       eq("number",2)
}

But I'm not sure if it reduces the queries to the database, or I'm just making a fool of myself and creating even bigger files and reducing the speed of my app by doing this.

any idea?

Upvotes: 1

Views: 1170

Answers (1)

Beryllium
Beryllium

Reputation: 12998

I have compared three versions of your query using

  • Grails 2.4.4, default settings for caches in a the Grails application
  • PostgreSQL 8.4, SQL statement logging has been turned on to count/see the SQL queries.

The first versions one using two calls on the Grails domain class:

def query1() {
  Catalog a = Catalog.findByName('a');
  log.info(a)

  Element b = Element.findByCatalogAndPos(a, 2);
  log.info(b)

  render(b.toString())
}

The 2nd one using criteria

def query2() {
  Element b = Element.createCriteria().get {
    catalog {
      eq("name", "a")
    }
    eq("pos", 2)
  }

  render(b.toString())
}

and the last one using a where query

def query3() {
  def query = Element.where {
    catalog.name == "a" && pos == 2
  }

  Element b = query.get()

  render(b.toString())
}

The first one results in two SQL queries, the other ones will only send one query to the database (using an inner join from Element to Catalog).

As for readability/expressiveness, choose the 3rd version: It expresses your intention in a single line, and it's the most compact version.

As for performance, choose the 2nd or the 3rd version. Under high load, many concurrent users/requests, the number of queries does matter. This might not be an issue for all applications.

Anway, I'd always choose the 3rd version for the expressiveness; and it will scale, if the query conditions gets more complex over the time.


Update

The SQL statements used by the 1st version:

select this_.id as id1_1_0_, this_.version as version2_1_0_, this_.date_created as date_cre3_1_0_, this_.last_updated as last_upd4_1_0_, this_.name as name5_1_0_, this_.remark as remark6_1_0_ 
  from catalog this_ 
  where this_.name=$1 limit $2
Parameter: $1 = 'a', $2 = '1'

select this_.id as id1_2_0_, this_.version as version2_2_0_, this_.catalog_id as catalog_3_2_0_, this_.date_created as date_cre4_2_0_, this_.last_updated as last_upd5_2_0_, this_.pos as pos6_2_0_, this_.remark as remark7_2_0_ 
  from element this_ 
  where this_.catalog_id=$1 and this_.pos=$2 limit $3
Parameter: $1 = '10', $2 = '2', $3 = '1'

The SQL statement for the 2nd and 3rd version:

select this_.id as id1_2_1_, this_.version as version2_2_1_, this_.catalog_id as catalog_3_2_1_, this_.date_created as date_cre4_2_1_, this_.last_updated as last_upd5_2_1_, this_.pos as pos6_2_1_, this_.remark as remark7_2_1_, catalog_al1_.id as id1_1_0_, catalog_al1_.version as version2_1_0_, catalog_al1_.date_created as date_cre3_1_0_, catalog_al1_.last_updated as last_upd4_1_0_, catalog_al1_.name as name5_1_0_, catalog_al1_.remark as remark6_1_0_ 
  from element this_ inner join catalog catalog_al1_ 
    on this_.catalog_id=catalog_al1_.id 
    where (catalog_al1_.name=$1) and this_.pos=$2
Parameter: $1 = 'a', $2 = '2'

Upvotes: 2

Related Questions