'Querying using `database/sql` is significantly slower than querying the database directly

I'm running the same query against a local postgresql instance using a golang application, and using psql. The timings differ greatly and I'm wondering why. Using explain/analyze the query took 1ms, using database/sql in golang, it took 24ms. I've added my code snippets below. I realize that explain/analyze may not be equivalent to querying the database directly, and there may be some network latency involved as well, however the discrepancy is still significant. Why is there such a discrepancy?

edit: I've tried the above with a sample size of 10+ queries, and the discrepancy still holds true.

postgres=# \timing
Timing is on.
postgres=# select 1;
 ?column?
----------
        1
(1 row)

Time: 2.456 ms
postgres=# explain analyze select 1;
                                     QUERY PLAN
------------------------------------------------------------------------------------
 Result  (cost=0.00..0.01 rows=1 width=4) (actual time=0.002..0.002 rows=1 loops=1)
 Planning Time: 0.017 ms
 Execution Time: 0.012 ms
(3 rows)

Time: 3.748 ms
package main

    import (
        "database/sql"
        "fmt"
        _ "github.com/lib/pq"
        "time"
    )

    func main() {
        // setup database connection
        db, err := sql.Open("postgres", "host='localhost' port=5432 user='postgres' password='' dbname='postgres' sslmode=disable")
        if err != nil {
            panic(err)
        }

        // query database
        firstQueryStart := time.Now()
        _, err = db.Query("select 1;")
        firstQueryEnd := time.Now()
        if err != nil {
            panic(err)
        }
        fmt.Println(fmt.Sprintf("first query took %s", firstQueryEnd.Sub(firstQueryStart).String()))

        //run the same query a second time and measure the timing
        secondQueryStart := time.Now()
        _, err = db.Query("select 1;")
        secondQueryEnd := time.Now()
        if err != nil {
            panic(err)
        }
        fmt.Println(fmt.Sprintf("second query took %s", secondQueryEnd.Sub(secondQueryStart).String()))
    }
first query took 13.981435ms
second query took 13.343845ms


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source