X-Original-To: pgsql-performance-postgresql.org@localhost.postgresql.org Received: from localhost (av.hub.org [200.46.204.144]) by postgresql.org (Postfix) with ESMTP id E68319DCD4E for ; Sat, 4 Mar 2006 03:01:52 -0400 (AST) Received: from postgresql.org ([200.46.204.71]) by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024) with ESMTP id 68505-04 for ; Sat, 4 Mar 2006 03:01:51 -0400 (AST) X-Greylist: from auto-whitelisted by SQLgrey- Received: from stark.xeocode.com (stark.xeocode.com [216.58.44.227]) by postgresql.org (Postfix) with ESMTP id 195319DCD15 for ; Sat, 4 Mar 2006 03:01:39 -0400 (AST) Received: from localhost ([127.0.0.1] helo=stark.xeocode.com) by stark.xeocode.com with smtp (Exim 3.36 #1 (Debian)) id 1FFQlj-0003eJ-00; Sat, 04 Mar 2006 02:01:35 -0500 To: Alex Adriaanse Cc: pgsql-performance@postgresql.org Subject: Re: Bad row estimates References: <4408E91C.90104@innovacomputing.com> In-Reply-To: <4408E91C.90104@innovacomputing.com> From: Greg Stark Organization: The Emacs Conspiracy; member since 1992 Date: 04 Mar 2006 02:01:35 -0500 Message-ID: <87wtfasng0.fsf@stark.xeocode.com> Lines: 42 User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.4 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Virus-Scanned: by amavisd-new at hub.org X-Spam-Status: No, score=0.129 required=5 tests=[AWL=0.129] X-Spam-Score: 0.129 X-Spam-Level: X-Archive-Number: 200603/19 X-Sequence-Number: 17456 Alex Adriaanse writes: > SELECT count(*) FROM test_table_1 > INNER JOIN test_table_2 ON > (test_table_2.s_id = 13300613 AND test_table_1.id = test_table_2.n_id) > WHERE now() BETWEEN test_table_1.start_ts AND test_table_1.end_ts > AND test_table_1.id = test_table_1.g_id; I don't know if this is the entire answer but this query is touching on two of Postgres's specific difficulties in analyzing statistics: The "now() BETWEEN test_table_1.start_ts AND test_table_1.end_ts can't be answered completely using a btree index. You could try using a GIST index here but I'm not clear how much it would help you (or how much work it would be). The "test_table_1.id = test_table_1.g_id" clause depends on intercolumn "correlation" which Postgres doesn't make any attempt at analyzing. That's why you've found that no matter how much you increase the statitics goal it can't come up with a better estimate. Actually the "now() between ..." clause also suffers from the inter-column dependency issue which is why the estimates for it are off as well. > However, if I add a boolean column named "equal_ids" to test_table_1 with > the value (test_table_1.id = test_table_1.g_id), and use that in the query > instead of the equality it does make a much better row estimate. One thing you could try is making an expression index on that expression. You don't need to actually have a redundant column bloating your table. In 8.1 I believe Postgres will even calculate statistics for these expression indexes. In fact you could go one step further and try a partial index like: CREATE INDEX eq_start ON test_table (start_ts) WHERE id = g_id The ideal combination might be to create a partial GIST index :) (I don't think the end_ts in the index is buying you much, despite its appearance in the Index Cond in the plan.) -- greg