Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kIOu7-0007ci-L7 for pgsql-performance@arkaria.postgresql.org; Wed, 16 Sep 2020 04:18:47 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1kIOu5-0000pY-Nt for pgsql-performance@arkaria.postgresql.org; Wed, 16 Sep 2020 04:18:45 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kIOu5-0000pQ-At for pgsql-performance@lists.postgresql.org; Wed, 16 Sep 2020 04:18:45 +0000 Received: from mail-io1-xd41.google.com ([2607:f8b0:4864:20::d41]) by magus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1kIOu2-0001Ef-9l for pgsql-performance@lists.postgresql.org; Wed, 16 Sep 2020 04:18:44 +0000 Received: by mail-io1-xd41.google.com with SMTP id r9so6797812ioa.2 for ; Tue, 15 Sep 2020 21:18:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=telsasoft-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to :user-agent; bh=JbFaWgX86td/ZC6gae0mSXG3q3Ecbza4Y7NLyZlSIkQ=; b=PYc76ieVxrfX0zfvrVnwh26HbDvvi6/MU8W94q21bn8K7DhFB5swZsbt49GxMKdXeb uhsAbiXL5oEUQz00dMJ2a23UM3nOrWcRPcEBdj2tS/GbeqalSreSDZGP2+H7lmkQioSf +aaKvxc7WF6UbJrsCDh38TkBwV0sifxBYnHNf2e3BK2+MER/wmwYYr+zl7h1wgLdFG8R J/1TcMjcYCtnT6yzw3csQAstgfijrzL7bxK7ZYEET8sYNbFRRH6hPv58ecnFMAFwxjwF XYhAMvM7F363JT6/tMCNFtrHM18yZFUJNEowAMezza5R8kJZp7afhLIvHCyKRlheW6iJ +ZiQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to:user-agent; bh=JbFaWgX86td/ZC6gae0mSXG3q3Ecbza4Y7NLyZlSIkQ=; b=t+N8+tQh4aYDxNPyOT0PC+WVV7iOZclt1THOWMlHybIK+w8NcCu1d64XMs6BEgu3LB 9IqJTBKrKNf7nvNwlDKvtPht4Oy2bl12ZwQYZWjkHEAOf9gmu8GqJmrg9xmOA2Ju7kIK b9IsOp7dVyrPEBjID0XSGw4KYaRZ/jNfVlwBpQpa2160rPsTaAITa7DFwsI5aold4Arj m4mNOeRzluMQN+Sr/Lv3Y1VunD6U82KbS8+odF8hZVRfHTnOUOHAkHtPrWTORx9WR2xU aRDo1JRJP/ySPEwCKxHiZd9HT1zwJLmKc2ekfn4LhWQTChegYSvO5HsBfo1+4xI+3ISe caZw== X-Gm-Message-State: AOAM531nqawuCr6ivgc73xW1sKpZavsNgRJwbAq4LSVDXhmnKEQeywXK QsAWi15xHoZMSD8jCB6Vh8nVd2w4dkWrrA== X-Google-Smtp-Source: ABdhPJwNvN5ZTvaJ8v7aqUsc8cUJQ+jctOlwKj/MAedNQ7ICOpPNm2F++JE8l1cllQ5LBfiZD98JBQ== X-Received: by 2002:a05:6638:1304:: with SMTP id r4mr21183620jad.116.1600229917902; Tue, 15 Sep 2020 21:18:37 -0700 (PDT) Received: from pryzbyj.telsasoft (charmander.telsasoft.com. [50.244.222.1]) by smtp.gmail.com with ESMTPSA id o8sm10373644ilb.64.2020.09.15.21.18.36 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 15 Sep 2020 21:18:36 -0700 (PDT) Received: by pryzbyj.telsasoft (Postfix, from userid 1000) id 25DF380055E; Tue, 15 Sep 2020 23:18:35 -0500 (CDT) Date: Tue, 15 Sep 2020 23:18:35 -0500 From: Justin Pryzby To: Nagaraj Raj Cc: Pgsql Performance Subject: Re: Single column vs composite partial index Message-ID: <20200916041834.GW18552@telsasoft.com> References: <1709308869.2763890.1600209204171.ref@mail.yahoo.com> <1709308869.2763890.1600209204171@mail.yahoo.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <1709308869.2763890.1600209204171@mail.yahoo.com> User-Agent: Mutt/1.9.4 (2018-02-28) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk On Tue, Sep 15, 2020 at 10:33:24PM +0000, Nagaraj Raj wrote: > Hi, > I'm running one query, and I created two types of index one is composite and the other one with single column one and query planner showing almost the same cost for both index bitmap scan, I'm not sure which is appropriate to keep in production tables. You're asking whether to keep one index or the other ? It depends on *all* the queries you'll run, not just this one. The most general thing to do would be to make multiple, single column indexes, and let the planner figure out which is best (it might bitmap-AND or -OR them together). However, for this query, you can see the 2nd query is actually faster (2ms vs 56ms) - the cost is an estimate based on a model. The actual performance might change based on thing like maintenance like reindex, cluster, vacuum, hardware, and DB state (like cached blocks). And postgres version. The rowcount estimates are bad. Maybe you need to ANALYZE the table (or adjust the autoanalyze thresholds), or evaluate if there's a correlation between columns. Bad rowcount estimates beget bad plans and poor performance. Also: you could use explain(ANALYZE,BUFFERS). I think the fast plan would be possible with a tiny BRIN index on load_dttm. (Possibly combined indexes on actv_code or others). If you also have a btree index on time, then you can CLUSTER on it (and analyze) and it might improve that plan further (but would affect other queries, too). > explain analyze SELECT BAN, SUBSCRIBER_NO, ACTV_CODE, ACTV_RSN_CODE, EFFECTIVE_DATE, TRX_SEQ_NO, LOAD_DTTM, rnk AS RNK  FROM ( SELECT CT.BAN, CT.SUBSCRIBER_NO, CT.ACTV_CODE, CT.ACTV_RSN_CODE, CT.EFFECTIVE_DATE, CT.TRX_SEQ_NO, CT.LOAD_DTTM, row_number() over (partition by CT.BAN, CT.SUBSCRIBER_NO, CT.ACTV_CODE, CT.ACTV_RSN_CODE order by CT.TRX_SEQ_NO DESC, CT.LOAD_DTTM DESC) rnk FROM SAM_T.L_CSM_TRANSACTIONS CT WHERE CT.ACTV_CODE in ( 'NAC', 'CAN', 'RSP', 'RCL') AND LOAD_DTTM::DATE >= CURRENT_DATE - 7 ) S WHERE RNK = 1 > 1st Index with single column: > CREATE INDEX l_csm_transactions_load_dttm_idx1    ON sam_t.l_csm_transactions USING btree    (load_dttm ASC NULLS LAST) > /*"Subquery Scan on s  (cost=32454.79..33555.15 rows=129 width=61) (actual time=56.473..56.473 rows=0 loops=1) >   Filter: (s.rnk = 1) >   ->  WindowAgg  (cost=32454.79..33231.52 rows=25891 width=61) (actual time=56.472..56.472 rows=0 loops=1) >         ->  Sort  (cost=32454.79..32519.51 rows=25891 width=53) (actual time=56.470..56.470 rows=0 loops=1) >               Sort Key: ct.ban, ct.subscriber_no, ct.actv_code, ct.actv_rsn_code, ct.trx_seq_no DESC, ct.load_dttm DESC >               Sort Method: quicksort  Memory: 25kB >               ->  Bitmap Heap Scan on l_csm_transactions ct  (cost=1271.13..30556.96 rows=25891 width=53) (actual time=56.462..56.462 rows=0 loops=1) >                     Recheck Cond: ((actv_code)::text = ANY ('{NAC,CAN,RSP,RCL}'::text[])) >                     Filter: ((load_dttm)::date >= (CURRENT_DATE - 7)) >                     Rows Removed by Filter: 79137 >                     Heap Blocks: exact=23976 >                     ->  Bitmap Index Scan on l_csm_transactions_actv_code_idx1  (cost=0.00..1264.66 rows=77673 width=0) (actual time=6.002..6.002 rows=79137 loops=1) > Planning Time: 0.270 ms > Execution Time: 56.639 ms"*/ > 2nd one with composite and partial index: > CREATE INDEX l_csm_transactions_actv_code_load_dttm_idx1    ON sam_t.l_csm_transactions USING btree    (actv_code COLLATE pg_catalog."default" ASC NULLS LAST, (load_dttm::date) DESC NULLS FIRST)    WHERE actv_code::text = ANY (ARRAY['NAC'::character varying, 'CAN'::character varying, 'RSP'::character varying, 'RCL'::character varying]::text[]); > > /*"Subquery Scan on s  (cost=32023.15..33123.52 rows=129 width=61) (actual time=2.256..2.256 rows=0 loops=1) >   Filter: (s.rnk = 1) >   ->  WindowAgg  (cost=32023.15..32799.88 rows=25891 width=61) (actual time=2.255..2.255 rows=0 loops=1) >         ->  Sort  (cost=32023.15..32087.88 rows=25891 width=53) (actual time=2.254..2.254 rows=0 loops=1) >               Sort Key: ct.ban, ct.subscriber_no, ct.actv_code, ct.actv_rsn_code, ct.trx_seq_no DESC, ct.load_dttm DESC >               Sort Method: quicksort  Memory: 25kB >               ->  Bitmap Heap Scan on l_csm_transactions ct  (cost=1449.32..30125.32 rows=25891 width=53) (actual time=2.247..2.247 rows=0 loops=1) >                     Recheck Cond: (((load_dttm)::date >= (CURRENT_DATE - 7)) AND ((actv_code)::text = ANY ('{NAC,CAN,RSP,RCL}'::text[]))) >                     ->  Bitmap Index Scan on l_csm_transactions_actv_code_load_dttm_idx1  (cost=0.00..1442.85 rows=25891 width=0) (actual time=2.244..2.245 rows=0 loops=1) >                           Index Cond: ((load_dttm)::date >= (CURRENT_DATE - 7)) > Planning Time: 0.438 ms > Execution Time: 2.303 ms"*/