I am facing an issue that Even after creating a GIN INDEX execution plan is taking much time.

select email from customer where lower(email) like '%gmail';
CREATE INDEX idx1  ON customer USING gin  (lower(email) gin_trgm_ops);.

Index created as  "idx1" gin (lower(email::text) gin_trgm_ops)

explain plan gives as below

 Bitmap Heap Scan on customer  (cost=168.51..367.36 rows=194 width=22) (actual time=381.844..1807.673 rows=931488 loops=1)
   Recheck Cond: (lower((email)::text) ~~ '%gmail.com'::text)
   Rows Removed by Index Recheck: 556
   Heap Blocks: exact=53254
   ->  Bitmap Index Scan on idx1  (cost=0.00..168.46 rows=194 width=0) (actual time=372.263..372.263 rows=933383 loops=1)
         Index Cond: (lower((email)::text) ~~ '%gmail.com'::text)
 Planning time: 0.741 ms
 Execution time: 1988.646 ms
(8 rows)

Please let me know if this can be fine-tuned further

  • Run vacuum full analyze customer, and can you show us the result of \d customer – Evan Carroll Jan 9 at 3:26
  • Vacuum full was already completed and has reclaimed the space on the customer table............... Is there a way to create index in a different way and check – Shaju M.K Jan 9 at 3:56
  • \d customer email | character varying(100) | "mkt_customer_pk" PRIMARY KEY, btree (customerid) "a1" btree (age) "customer_email_gin_trgm_idx" gin (lower(email::text) gin_trgm_ops) – Shaju M.K Jan 9 at 3:59
  • Hi Guys Can some one help with this issue? – Shaju M.K Jan 9 at 6:22
  • 1
    how many rows do you even have in this table? – Evan Carroll Jan 9 at 6:27

You are returning 1 million rows. Returning 1 million rows is going to take some time. Especially when it has to do a pattern matching recheck of each row. How fast do you expect this to be?

Your best bet is fixing things on the application side. Why do you need a million rows? What are doing with them? And if you do need to return that many, why do you need to do it so often that it matters if it takes an extra second to do? But beyond that:

  • Get a faster computer.
  • Upgrade to a recent version of PostgreSQL and see if you can get parallel execution (that would depend on what percentage of your table is being returned by this query)
  • Get rid of the "lower" function and use "ilike" rather than "like". Indexes based on gin_trgm_ops support "ilike" queries naturally with no special steps needed.
  • Use an ordinary btree index on reverse(lower(email)) so that the wild card is at the end rather than the beginning of the query string. Better yet, store the email in that form to start with, so expression indexes are not needed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.