Your Question

version: v1.22.4

I have a query which is not slow when I use explain analyze in pgsql:

pgsql=> explain analyze SELECT * FROM "employees" WHERE (organization_id = 'XYZ') AND is_duplicate = false;
                                                  QUERY PLAN
--------------------------------------------------------------------------------------------------------------
 Seq Scan on employees  (cost=0.00..1072.86 rows=4245 width=232) (actual time=0.845..5.401 rows=4283 loops=1)
   Filter: ((NOT is_duplicate) AND (organization_id = 'XYZ'::text))
   Rows Removed by Filter: 18109
 Planning Time: 1.005 ms
 Execution Time: 5.627 ms

I then try to include network latency as well:

pgsql=> \timing
Timing is on.
pgsql=> SELECT * FROM "employees" WHERE (organization_id = 'XYZ') AND is_duplicate = false;
Time: 1742.852 ms (00:01.743)

Which is not the best, but still ok considering I am running pgsql from China while the Postgres instance is in us-central on GCP.

However, when using GORM to query the data in a golang app, based on the GORM's logger output, it is extremely slow. The code runs in an GCP instance in the same network (us-central1 on GCP) as the Postgres instance, where network latency is minimized. My code looks like:

query := e.db.Orm.WithContext(ctx).Model(&employees).
                 Preload("A").
        Preload("A.X").
        Preload("B").
        Preload("B.Y").
        Preload("C").
        Where("organization_id = ?", organizationID).
        Where("is_duplicate = ?", false)

The employees table has 20 columns. Only has index on primary key. Almost all rows have is_duplicate = false.

The resulting pre-load query performance is fine:

  elapsed: 1283338  // 1.28ms
  message: "trace sql execution"   
  rowsAffected: 10   
  sql: "SELECT * FROM "C" WHERE "C"."id" IN ('1','2','3','4','5','6','7','8','9','10')"   
  tag: "employees"   
  timestamp: "2022-01-08T03:31:47.353114137Z" 

but querying the 4283 employees take almost 6s:

elapsed: 5934930249  // 5934.93ms
message: "trace sql execution"   
rowsAffected: 4283   
sql: "SELECT * FROM "employees" WHERE (organization_id = 'XYZ') AND is_duplicate = false"   
tag: "employees"   
timestamp: "2022-01-08T03:31:52.448252349Z" 

I suspect GORM introduced significant amount of latency in my cause. Where did I do wrong? Where is the latency coming from? Any suggestion to improve the performance with GROM?

--- update --- Looks like the Preload has something to do with this. I replace some preload with joins in my code and seeing some improvement:

query := e.db.Orm.WithContext(ctx).Model(&employees).
    Joins("A").
    // Preload("A.X"). looks like GORM doesn't support nested joins preloading
    Joins("B").
    // Preload("B.Y"). looks like GORM doesn't support nested joins preloading
    Joins("C").
    Where("organization_id = ?", organizationID).
    Where("is_duplicate = ?", false)

and that reduce quite a lot of latency. However, looks like GORM doesn't support nested joins preloading, so I can't simply change to Joins.

The document you expected this should be explained

Expected answer

Understand the source of the latency and get suggestions on how to reduce it.

Comment From: Heliner

What is the definition statement of the table of "employees" or the col num of the table? The number of columns may greatly affect the performance of orm

Comment From: jinzhu

GORM v1.23 have improved this a lot, please upgrade to the latest version, thank you.