Received: from makus.postgresql.org (makus.postgresql.org [98.129.198.125]) by mail.postgresql.org (Postfix) with ESMTP id CD8131B25E49 for ; Thu, 15 Mar 2012 05:32:29 -0300 (ADT) Received: from mail-pz0-f47.google.com ([209.85.210.47]) by makus.postgresql.org with esmtp (Exim 4.72) (envelope-from ) id 1S866m-0003yJ-43 for pgsql-performance@postgresql.org; Thu, 15 Mar 2012 08:32:29 +0000 Received: by dado14 with SMTP id o14so4778118dad.34 for ; Thu, 15 Mar 2012 01:32:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=message-id:date:from:user-agent:mime-version:to:subject :content-type:content-transfer-encoding; bh=RBOTmq+H7W45nhGehd/KT+YpyHbBaSecVlAW9rM8z9Y=; b=B2j2vQq2du/xwnHcYs3RS91Uezyv8J8ULspO5BhynPpX3T3ySGn6abIRQC9kMPJI8x km+sVXDjTByuQgR2PqyROzvsAql1LhRZkyMSw7i7d+6lWJRCQW1Mhld9wkLuJjU0TUFo aRCs4GgEc+IQgRZEu592c6MK1f1MiHppabYrHskzlLMsBZ5RX/lJXut6266JrfO1F8lp nrUTf5+PkRuzYRlZNqHZpCIoD9yYA4XZ16/MjdA/y6BEE0H8Lbl4KESYKGM/JrK7sP2x 73W+IAttrQ8x1cWtrGtjXf8VZ/truTk6Qe3A3oBTjC1cFSmoyLTzJLxGgj7QIX8ywil8 yduA== Received: by 10.68.208.196 with SMTP id mg4mr3300529pbc.108.1331800335310; Thu, 15 Mar 2012 01:32:15 -0700 (PDT) Received: from [192.168.1.46] ([116.226.41.123]) by mx.google.com with ESMTPS id r9sm1395840pbi.53.2012.03.15.01.32.12 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 15 Mar 2012 01:32:14 -0700 (PDT) Message-ID: <4F61A909.20109@gmail.com> Date: Thu, 15 Mar 2012 16:32:09 +0800 From: Rural Hunter User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:11.0) Gecko/20120312 Thunderbird/11.0 MIME-Version: 1.0 To: pgsql-performance@postgresql.org Subject: index choosing problem Content-Type: text/plain; charset=GB18030; format=flowed Content-Transfer-Encoding: 7bit X-Pg-Spam-Score: -2.6 (--) X-Archive-Number: 201203/106 X-Sequence-Number: 46556 I have a table with serveral million records. they are divided into about one hundred catagory(column cid). I created index includes the cid as the first column. I had a problem with some cids they only have few records comparing with other cids. Some of them only have serveral thousand rows. Some queries are not using index on the cids. I got the explain for the queries. Note: article_others_cid_time_style_idx is the index contains cid as the first column article_others_pkey is the primary key on an auto incremented column aid. # select count(*) from article_others; count --------- 6888459 (1 row) # select count(*) from article_others where cid=74; count ------- 4199 (1 row) 1. # explain select count(*) from article_others where cid=74; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------- Aggregate (cost=32941.95..32941.96 rows=1 width=0) -> Index Scan using article_others_cid_time_style_idx on article_others (cost=0.00..32909.34 rows=13047 width=0) Index Cond: (cid = 74) (3 rows) 2. # explain select aid from article_others where cid=74 limit 10; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------- Limit (cost=0.00..25.22 rows=10 width=8) -> Index Scan using article_others_cid_time_style_idx on article_others (cost=0.00..32909.34 rows=13047 width=8) Index Cond: (cid = 74) (3 rows) 3. # explain select aid from article_others where cid=74 order by aid desc limit 10; QUERY PLAN ------------------------------------------------------------------------------------------------------------------- Limit (cost=0.00..1034.00 rows=10 width=8) -> Index Scan Backward using article_others_pkey on article_others (cost=0.00..1349056.65 rows=13047 width=8) Filter: (cid = 74) (3 rows) 4. # explain select aid from article_others where cid=74 order by aid desc limit 1; QUERY PLAN ------------------------------------------------------------------------------------------------------------------- Limit (cost=0.00..103.40 rows=1 width=8) -> Index Scan Backward using article_others_pkey on article_others (cost=0.00..1349060.65 rows=13047 width=8) Filter: (cid = 74) (3 rows) 5. # explain select max(aid) from article_others where cid=74; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------- Result (cost=104.70..104.71 rows=1 width=0) InitPlan 1 (returns $0) -> Limit (cost=0.00..104.70 rows=1 width=8) -> Index Scan Backward using article_others_pkey on article_others (cost=0.00..1365988.55 rows=13047 width=8) Index Cond: (aid IS NOT NULL) Filter: (cid = 74) (6 rows) Now the query 3-5 using article_others_pkey are quite slow. The rows for cid 74 are very old and seldom get updated. I think pg needs to scan quite a lot on article_others_pkey before it gets the rows for cid 74. The same query for other cids with new and majority of rows runs very fast. for example: # explain select max(aid) from article_others where cid=258; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------- Result (cost=1.54..1.55 rows=1 width=0) InitPlan 1 (returns $0) -> Limit (cost=0.00..1.54 rows=1 width=8) -> Index Scan Backward using article_others_pkey on article_others (cost=0.00..1366260.55 rows=889520 width=8) Index Cond: (aid IS NOT NULL) Filter: (cid = 258) So I think if pg chooses to use index article_others_cid_time_style_idx the performance would be much better. or any other solution I can take to improve the query performance for those cids like 74? Another question, why the plan shows rows=13047 for cid=74 while actually it only has 4199 rows? There is almost no data changes for cid 74 and I just vacuum/analyzed the table this morning.