pg.ddx.io  pgsql-performance@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Laurent Martelli <laurent.martelli@enercoop.org>
To: pgsql-performance@postgresql.org
Subject: IS NOT NULL and LEFT JOIN
Date: Sun, 19 Oct 2014 06:10:50 +0200
Message-ID: <544339CA.5090202@enercoop.org> (raw)
List-Unsubscribe:  <mailto:majordomo@postgresql.org?body=unsub%20pgsql-performance>

Hello there,

I have a strange query plan involving an IS NOT NULL and a LEFT JOIN.

I grant you that the query can be written without the JOIN on 
user_user_info,
but it is generated like this by hibernate. Just changing the IS NOT 
NULL condition
to the other side of useless JOIN makes a big difference in the query plan :

-- THE BAD ONE : given the selectivity on c.name and c.email, barely 
more than one row will ever be returned
explain analyze select c.*
        from contact_contact c
        left outer join user_user_info u on c.user_info=u.id
        left outer join contact_address a on c.address=a.id
       where lower(c.name)='martelli'
         and c.email='dsfze@ezrfz.com' or u.id is not null;
                                                            QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------
  Hash Left Join  (cost=1.83..2246.76 rows=59412 width=4012) (actual 
time=53.645..53.645 rows=0 loops=1)
    Hash Cond: (c.user_info = u.id)
    Filter: (((lower((c.name)::text) = 'martelli'::text) AND 
((c.email)::text = 'dsfze@ezrfz.com'::text)) OR (u.id IS NOT NULL))
    Rows Removed by Filter: 58247
    ->  Seq Scan on contact_contact c  (cost=0.00..2022.12 rows=59412 
width=4012) (actual time=0.007..6.892 rows=58247 loops=1)
    ->  Hash  (cost=1.37..1.37 rows=37 width=8) (actual 
time=0.029..0.029 rows=37 loops=1)
          Buckets: 1024  Batches: 1  Memory Usage: 2kB
          ->  Seq Scan on user_user_info u  (cost=0.00..1.37 rows=37 
width=8) (actual time=0.004..0.015 rows=37 loops=1)
  Planning time: 0.790 ms
  Execution time: 53.712 ms

-- THE GOOD ONE (test IS NOT NULL on contact0_.user_info instead of 
userinfo1_.id)
explain analyze select c.*
        from contact_contact c
        left outer join user_user_info u on c.user_info=u.id
        left outer join contact_address a on c.address=a.id
       where lower(c.name)='martelli'
         and c.email='dsfze@ezrfz.com' or c.user_info is not null;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------
  Bitmap Heap Scan on contact_contact c  (cost=8.60..16.41 rows=1 
width=4012) (actual time=0.037..0.037 rows=0 loops=1)
    Recheck Cond: (((email)::text = 'dsfze@ezrfz.com'::text) OR 
(user_info IS NOT NULL))
    Filter: (((lower((name)::text) = 'martelli'::text) AND 
((email)::text = 'dsfze@ezrfz.com'::text)) OR (user_info IS NOT NULL))
    ->  BitmapOr  (cost=8.60..8.60 rows=2 width=0) (actual 
time=0.034..0.034 rows=0 loops=1)
          ->  Bitmap Index Scan on idx_contact_email (cost=0.00..4.30 
rows=2 width=0) (actual time=0.027..0.027 rows=0 loops=1)
                Index Cond: ((email)::text = 'dsfze@ezrfz.com'::text)
          ->  Bitmap Index Scan on contact_contact_user_info_idx  
(cost=0.00..4.30 rows=1 width=0) (actual time=0.007..0.007 rows=0 loops=1)
                Index Cond: (user_info IS NOT NULL)
  Planning time: 0.602 ms
  Execution time: 0.118 ms

My tables are as follow, and I use postgres 9.4 :

                                            Table « public.contact_contact »
         Colonne         |            Type             | Modificateurs | Stockage | Cible de statistiques | Description
------------------------+-----------------------------+---------------+----------+-----------------------+-------------
  id                     | bigint                      | non NULL      | plain    |                       |
  archived               | boolean                     |               | plain    |                       |
  version                | integer                     |               | plain    |                       |
  created_on             | timestamp without time zone |               | plain    |                       |
  updated_on             | timestamp without time zone |               | plain    |                       |
  actor_ref              | character varying(255)      |               | extended |                       |
  addressl1              | character varying(255)      |               | extended |                       |
  comment                | text                        |               | extended |                       |
  contact_partner_ok     | boolean                     |               | plain    |                       |
  date_of_birth          | date                        |               | plain    |                       |
  email                  | character varying(255)      |               | extended |                       |
  email_pro              | character varying(255)      |               | extended |                       |
  fax                    | character varying(255)      |               | extended |                       |
  first_name             | character varying(255)      |               | extended |                       |
  fixed_phone1           | character varying(255)      |               | extended |                       |
  fixed_phone2           | character varying(255)      |               | extended |                       |
  fixed_phone_pro        | character varying(255)      |               | extended |                       |
  import_key1            | character varying(255)      |               | extended |                       |
  import_key2            | character varying(255)      |               | extended |                       |
  koala_id               | character varying(255)      |               | extended |                       |
  mobile_phone_perso     | character varying(255)      |               | extended |                       |
  mobile_phone_pro       | character varying(255)      |               | extended |                       |
  name                   | character varying(255)      | non NULL      | extended |                       |
  ola_email              | character varying(255)      |               | extended |                       |
  ola_phone              | character varying(255)      |               | extended |                       |
  person_category_select | character varying(255)      |               | extended |                       |
  web_site               | character varying(255)      |               | extended |                       |
  year_of_birth          | integer                     |               | plain    |                       |
  created_by             | bigint                      |               | plain    |                       |
  updated_by             | bigint                      |               | plain    |                       |
  action_event_source    | bigint                      |               | plain    |                       |
  address                | bigint                      |               | plain    |                       |
  address_pro            | bigint                      |               | plain    |                       |
  jobtitle               | bigint                      |               | plain    |                       |
  merged_with            | bigint                      |               | plain    |                       |
  nationality_country    | bigint                      |               | plain    |                       |
  origin                 | bigint                      |               | plain    |                       |
  place_of_birth_address | bigint                      |               | plain    |                       |
  title                  | bigint                      |               | plain    |                       |
  user_info              | bigint                      |               | plain    |                       |
  import_origin          | character varying(255)      |               | extended |                       |
  duplicates             | bigint                      |               | plain    |                       |
Index :
     "contact_contact_pkey" PRIMARY KEY, btree (id)
     "uk_bx19539x7h0y0w4p4uw9gnqbo" UNIQUE CONSTRAINT, btree (koala_id)
     "uk_vg25de8jcu18m89o9dy2n4fe" UNIQUE CONSTRAINT, btree (import_key1)
     "contact_contact_action_event_source_idx" btree (action_event_source)
     "contact_contact_address_idx" btree (address)
     "contact_contact_address_l1_idx" btree (addressl1)
     "contact_contact_address_pro_idx" btree (address_pro)
     "contact_contact_jobtitle_idx" btree (jobtitle)
     "contact_contact_merged_with_idx" btree (merged_with)
     "contact_contact_name_idx" btree (name)
     "contact_contact_nationality_country_idx" btree (nationality_country)
     "contact_contact_origin_idx" btree (origin)
     "contact_contact_place_of_birth_address_idx" btree (place_of_birth_address)
     "contact_contact_title_idx" btree (title)
     "contact_contact_user_info_idx" btree (user_info)
     "idx_contact_email" btree (email)
     "idx_contact_lower_name" btree (lower(name::text))
     "idx_contact_search_name" btree (lower(name::text), lower(first_name::text))
Contraintes de clés étrangères :
     "fk_8dj7rw3jrdxk4vxbi6vony0ne" FOREIGN KEY (created_by) REFERENCES auth_user(id)
     "fk_9s1dhwrvw6lq74fvty6oj2wc5" FOREIGN KEY (address_pro) REFERENCES contact_address(id)
     "fk_9wjsgh8lt5ixbshx9pjwmjtk1" FOREIGN KEY (origin) REFERENCES crm_origin(id)
     "fk_ad53x8tdando1w1jdlyxcop9v" FOREIGN KEY (duplicates) REFERENCES contact_contact(id)
     "fk_edusucr1gdfj99vtm0a70gggg" FOREIGN KEY (title) REFERENCES contact_title(id)
     "fk_g7u75rjd754m7evn2alckjvka" FOREIGN KEY (merged_with) REFERENCES contact_contact(id)
     "fk_j72hkuq0337v6utjbf85hhvxg" FOREIGN KEY (action_event_source) REFERENCES crm_action_event_source(id)
     "fk_k73mcu7swia6uf6qpp4v6lwxf" FOREIGN KEY (updated_by) REFERENCES auth_user(id)
     "fk_mvpl7wudcdqgitmmsd900od97" FOREIGN KEY (place_of_birth_address) REFERENCES contact_address(id)
     "fk_onriw4jpgeuvhfk827amxry8k" FOREIGN KEY (address) REFERENCES contact_address(id)
     "fk_rpkvno8705gap9ejj4wnnb7hl" FOREIGN KEY (nationality_country) REFERENCES territory_country(id)
     "fk_s9fsy33u5a9ke8wee9mc2vpsx" FOREIGN KEY (user_info) REFERENCES user_user_info(id)
     "fk_t8uexb8lmgaftjsnn63eoty90" FOREIGN KEY (jobtitle) REFERENCES contact_jobtitle(id)

coopener=# \d+ user_user_info
                                         Table « public.user_user_info »
      Colonne     |            Type             | Modificateurs | Stockage | Cible de statistiques | Description
-----------------+-----------------------------+---------------+----------+-----------------------+-------------
  id              | bigint                      | non NULL      | plain    |                       |
  archived        | boolean                     |               | plain    |                       |
  version         | integer                     |               | plain    |                       |
  created_on      | timestamp without time zone |               | plain    |                       |
  updated_on      | timestamp without time zone |               | plain    |                       |
  full_name       | character varying(255)      |               | extended |                       |
  import_key      | character varying(255)      |               | extended |                       |
  import_username | character varying(255)      |               | extended |                       |
  today           | timestamp without time zone |               | plain    |                       |
  user_system_ok  | boolean                     |               | plain    |                       |
  created_by      | bigint                      |               | plain    |                       |
  updated_by      | bigint                      |               | plain    |                       |
  active_company  | bigint                      |               | plain    |                       |
  agency          | bigint                      |               | plain    |                       |
  internal_user   | bigint                      | non NULL      | plain    |                       |
Index :
     "user_user_info_pkey" PRIMARY KEY, btree (id)
     "uk_99o17944ddytysui6b05lxyb2" UNIQUE CONSTRAINT, btree (import_key)
     "uk_cqgrw75h35ts19uixn03rkjsu" UNIQUE CONSTRAINT, btree (internal_user)
     "uk_jtsvu4r7s12nnh9o2sloqyqv4" UNIQUE CONSTRAINT, btree (import_username)
     "user_user_info_active_company_idx" btree (active_company)
     "user_user_info_agency_idx" btree (agency)
     "user_user_info_full_name_idx" btree (full_name)
Contraintes de clés étrangères :
     "fk_cojxp4r7d8n2l135gy4xa4vak" FOREIGN KEY (active_company) REFERENCES contact_company(id)
     "fk_cqgrw75h35ts19uixn03rkjsu" FOREIGN KEY (internal_user) REFERENCES auth_user(id)
     "fk_k3riohsx7jrhxkxdmxyeqflq1" FOREIGN KEY (updated_by) REFERENCES auth_user(id)
     "fk_r3e16hs6puibteaby3rk42yg0" FOREIGN KEY (created_by) REFERENCES auth_user(id)
     "fk_t389sdkhi9owy0xbhec2nqp5w" FOREIGN KEY (agency) REFERENCES contact_agency(id)

coopener=# \d+ contact_address
                                           Table « public.contact_address »
        Colonne        |            Type             | Modificateurs | Stockage | Cible de statistiques | Description
----------------------+-----------------------------+---------------+----------+-----------------------+-------------
  id                   | bigint                      | non NULL      | plain    |                       |
  archived             | boolean                     |               | plain    |                       |
  version              | integer                     |               | plain    |                       |
  created_on           | timestamp without time zone |               | plain    |                       |
  updated_on           | timestamp without time zone |               | plain    |                       |
  addressl2            | character varying(255)      |               | extended |                       |
  addressl3            | character varying(255)      |               | extended |                       |
  addressl4            | character varying(255)      |               | extended |                       |
  addressl5            | character varying(255)      |               | extended |                       |
  addressl6            | character varying(255)      |               | extended |                       |
  certified_ok         | boolean                     |               | plain    |                       |
  consumption_place_ok | boolean                     |               | plain    |                       |
  full_name            | character varying(255)      |               | extended |                       |
  insee_code           | character varying(255)      |               | extended |                       |
  koala_id             | character varying(255)      |               | extended |                       |
  created_by           | bigint                      |               | plain    |                       |
  updated_by           | bigint                      |               | plain    |                       |
  addressl7country     | bigint                      |               | plain    |                       |
  commune              | bigint                      |               | plain    |                       |
Index :
     "contact_address_pkey" PRIMARY KEY, btree (id)
     "contact_address_address_l7_country_idx" btree (addressl7country)
     "contact_address_commune_idx" btree (commune)
     "contact_address_full_name_idx" btree (full_name)
Contraintes de clés étrangères :
     "fk_4yx7nnewflhyjdm5tue5qntbg" FOREIGN KEY (commune) REFERENCES territory_commune(id)
     "fk_5lwaygtve0ol8ma53picsdef" FOREIGN KEY (addressl7country) REFERENCES territory_country(id)
     "fk_p9svu5ssynimpuu0is3j396lt" FOREIGN KEY (updated_by) REFERENCES auth_user(id)
     "fk_rm0lcgnys2n97ad62jkm53qlt" FOREIGN KEY (created_by) REFERENCES auth_user(id)


Regards,
Laurent

view thread (9+ messages)  latest in thread

Message-ID: <544339CA.5090202@enercoop.org>
Permalink:  ../544339CA.5090202@enercoop.org/
Also on:    postgresql.org/message-id/544339CA.5090202@enercoop.org

 · 

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-performance@postgresql.org
  Cc: laurent.martelli@enercoop.org
  Subject: Re: IS NOT NULL and LEFT JOIN
  In-Reply-To: <544339CA.5090202@enercoop.org>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox