Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.80) (envelope-from ) id 1a1zXA-0008C2-4p for pgsql-performance@arkaria.postgresql.org; Thu, 26 Nov 2015 16:36:36 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.84) (envelope-from ) id 1a1zX9-0003oR-KM for pgsql-performance@arkaria.postgresql.org; Thu, 26 Nov 2015 16:36:35 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.84) (envelope-from ) id 1a1zVV-0001s6-7i for pgsql-performance@postgresql.org; Thu, 26 Nov 2015 16:34:53 +0000 Received: from nm11-vm7.bullet.mail.ir2.yahoo.com ([212.82.96.168]) by magus.postgresql.org with esmtps (TLS1.0:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.84) (envelope-from ) id 1a1zVN-00012k-IY for pgsql-performance@postgresql.org; Thu, 26 Nov 2015 16:34:52 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.co.uk; s=s2048; t=1448555683; bh=OUpIU/WDN7Y6eX1OYy0jcJcYps6bb/w6vbSj+uTT/6Y=; h=Date:From:Reply-To:To:In-Reply-To:References:Subject:From:Subject; b=OlRXKz+DWcJtuO6he22kQdyqeEYl8A/Gh48fmHVU4xj2+INfcZau3lct+zQQfo5Fhcc8DxRnTt7okwSnn/oWNOssq9vsef9Wxt1jGmIDXMel7IOxhFNTm5O2F4bYtnVT+/+3euxv1wzkygDKA5i+4CRd4ST203VQRqiz2BW159HPQf4Nc7HU9nGQxoT+PZnirAhEvFqPafgIROYDg5C8C2Ws406B7JQzj0CFOw7MwIaSGdHc/Sw/3CaNY9nloWntTlfKRUPBrUq8R8hn3xkUbL3aePp4mQ7++P18Lk9AStU9fPftInhfRzQH3M1hNbJSd37sdHqP+ahsuAC16jC1/g== Received: from [212.82.98.56] by nm11.bullet.mail.ir2.yahoo.com with NNFMP; 26 Nov 2015 16:34:43 -0000 Received: from [212.82.98.110] by tm9.bullet.mail.ir2.yahoo.com with NNFMP; 26 Nov 2015 16:34:43 -0000 Received: from [127.0.0.1] by omp1047.mail.ir2.yahoo.com with NNFMP; 26 Nov 2015 16:34:43 -0000 X-Yahoo-Newman-Property: ymail-3 X-Yahoo-Newman-Id: 768278.73187.bm@omp1047.mail.ir2.yahoo.com X-YMail-OSG: 3lexiFoVM1kzQ4D8IEHOl10lTxF3j6sq_oMMXAjYBqaLW2B5iec8hTQfN9SiS4E wvxGET7uIHv0hZpsG1DbEmbf2fLIuVawiXc.TWd4QmbhZsMZqkZ81sTWFfCjtqD_bMs7EbFLWnYX VUqIPwslQYIzfwMnm1ZB5nDGpZe4A.cmDUixmOA92y9oG5mGfBpgoqg5c87brAEEQ8zlf_mAN6s8 1g30oL.Sjd08CvGgWK7NT9vmtGB53z.HXJA6yV_FTnykIYy05MsOnUTPmo.85CvVBHEbXGiix5xc eKPOpBqbpAlj.ioM9TYgTKodSPhOLoPxAXfl9lY5WgPXlxVNWEg62ZU14w2Yki1mhorojb3IugA2 i.z.1l9rPc8nvrK8TQF9VlvG78N6eJJqbBFXUEDy3oTN4xoEmkfStY2PZSzPUlZ7vqMQ_4seYScq 371YzzcYOS45gSLOFsUzXePMvvrgKepgrKEEBBs1nAXk1RY8Gxp4.Ycv4.h4v0SErUXh45_dYPRW DYRNTFLOBwzJbmg-- Received: by 217.12.9.15; Thu, 26 Nov 2015 16:34:43 +0000 Date: Thu, 26 Nov 2015 16:34:35 +0000 (UTC) From: Glyn Astill Reply-To: Glyn Astill To: Glyn Astill , Pgsql-performance Message-ID: <1037814983.18183568.1448555675086.JavaMail.yahoo@mail.yahoo.com> In-Reply-To: <1077451263.18070016.1448554301343.JavaMail.yahoo@mail.yahoo.com> References: <1077451263.18070016.1448554301343.JavaMail.yahoo@mail.yahoo.com> Subject: Re: Index scan cost calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit Content-Length: 5005 X-Pg-Spam-Score: -2.7 (--) List-Archive: List-Help: List-ID: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-Mailing-List: pgsql-performance Precedence: bulk Sender: pgsql-performance-owner@postgresql.org ----- Original Message ----- > From: Glyn Astill > To: Pgsql-performance > Sent: Thursday, 26 November 2015, 16:11 > Subject: [PERFORM] Index scan cost calculation > > Hi All, > > Using pg 9.4.5 I'm looking at a table set up by a 3rd party application and > trying to figure out why a particular index is being chosen over another for > updates/deletes. > > From what I can see the reason is that plans using either index have the same > exactly the same cost. So rather I'm asking if there's something > glaringly obvious I'm missing, or is there anything I can to to get better > estimates. > > The table is as follows and has ~ 50M rows, ~ 4.5GB in size: > > CREATE TABLE tickets.seats > ( > recnum serial NOT NULL, > show numeric(8,0) NOT NULL, > type numeric(4,0) NOT NULL, > block character varying(8) NOT NULL, > "row" numeric(14,0) NOT NULL, > seat numeric(8,0) NOT NULL, > flag character varying(15) NOT NULL, > transno numeric(8,0) NOT NULL, > best numeric(4,0) NOT NULL, > "user" character varying(15) NOT NULL, > "time" numeric(10,0) NOT NULL, > date date NOT NULL, > date_reserved timestamp NOT NULL > ); > > Indexes: > "seats_index01" PRIMARY KEY, btree (show, type, best, block, > "row", seat) // (1094 MB) > "seats_index00" UNIQUE, btree (recnum) > // (2423 MB) > "seats_index02" UNIQUE, btree (show, type, best, block, flag, > "row", seat, recnum) // (2908 MB) > ^^ If those first two sizes look wrong, it's because they are; they should be the other way around. > default_statistics target is 100, and the following columns are non-default: > > attname | attstattarget > --------+--------------- > show | 1000 > type | 1000 > block | 2000 > row | 1000 > seat | 1000 > flag | 1000 > best | 1000 > > Increasing these further appears to make no noticeable difference. (pg_stats > here for these columns here: http://pastebin.com/2WQQec7N) > > An example query below shows that in some cases the seats_index02 index is being > chosen: > > # analyze verbose seats; > INFO: analyzing "tickets.seats" > INFO: "seats": scanned 593409 of 593409 pages, containing 50926456 > live rows and 349030 dead rows; 600000 rows in sample, 50926456 estimated total > rows > > # begin; > BEGIN > # explain analyze delete from seats where ("show" = 58919 AND > "type" = 1 AND "best" = 10 AND "block" = > 'GMA' AND "row" =26 AND "seat" = 15); > QUERY PLAN > ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- > Delete on seats (cost=0.56..4.59 rows=1 width=6) (actual time=0.480..0.480 > rows=0 loops=1) > -> Index Scan using seats_index02 on seats (cost=0.56..4.59 rows=1 width=6) > (actual time=0.452..0.453 rows=1 loops=1) > Index Cond: ((show = 58919::numeric) AND (type = 1::numeric) AND (best = > 10::numeric) AND ((block)::text = 'GMA'::text) AND ("row" = > 26::numeric) AND (seat = 15::numeric)) > Planning time: 2.172 ms > Execution time: 0.531 ms > (5 rows) > > But from my naive standpoint, seats_index01 is a better candidate: > > # abort; begin; > ROLLBACK > BEGIN > > # update pg_index set indisvalid = false where indexrelid = > 'seats_index02'::regclass; > # explain analyze delete from seats where ("show" = 58919 AND > "type" = 1 AND "best" = 10 AND "block" = > 'GMA' AND "row" =26 AND "seat" = 15); > QUERY PLAN > ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- > Delete on seats (cost=0.56..4.59 rows=1 width=6) (actual time=0.103..0.103 > rows=0 loops=1) > -> Index Scan using seats_index01 on seats (cost=0.56..4.59 rows=1 width=6) > (actual time=0.078..0.080 rows=1 loops=1) > Index Cond: ((show = 58919::numeric) AND (type = 1::numeric) AND (best = > 10::numeric) AND ((block)::text = 'GMA'::text) AND ("row" = > 26::numeric) AND (seat = 15::numeric)) > Planning time: 0.535 ms > Execution time: 0.146 ms > (5 rows) > > > In this instance, the time difference is not huge, however in some seemingly > random cases where there are a lot of rows with only the "seat" column > differing the choice of seats_index02 is much larger ~ 70ms vs 0.something ms > with seats_index01 > > I suspect some of the seemingly random cases could be where there's been an > update, followed by a delete since the last analyze, despite auto analyze > running fairly frequently. > > Any suggestions appreciated. > > Thanks > Glyn > > > -- > Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org) > To make changes to your subscription: > http://www.postgresql.org/mailpref/pgsql-performance > -- Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-performance