X-Original-To: pgsql-sql-postgresql.org@localhost.postgresql.org Received: from localhost (unknown [200.46.204.2]) by svr1.postgresql.org (Postfix) with ESMTP id 38D0CD1C9F3 for ; Fri, 23 Apr 2004 11:33:05 -0300 (ADT) Received: from svr1.postgresql.org ([200.46.204.71]) by localhost (neptune.hub.org [200.46.204.2]) (amavisd-new, port 10024) with ESMTP id 36877-07 for ; Fri, 23 Apr 2004 11:33:02 -0300 (ADT) Received: from vf.i-trade.hu (fw.i-trade.hu [212.92.1.62]) by svr1.postgresql.org (Postfix) with SMTP id D7B95D1C9E8 for ; Fri, 23 Apr 2004 11:32:57 -0300 (ADT) Received: (qmail 32195 invoked from network); 23 Apr 2004 14:13:20 -0000 Received: from szeged-130.i-trade.hu (HELO atesz) (212.92.7.130) by 0 with SMTP; 23 Apr 2004 14:13:19 -0000 From: "Antal Attila" To: Subject: Multi ordered select and indexing Date: Fri, 23 Apr 2004 16:33:14 +0200 Message-ID: <000301c4293f$ebf6b930$0b02010a@atesz> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook, Build 10.0.2627 Importance: Normal X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106 X-Virus-Scanned: by amavisd-new at postgresql.org X-Spam-Status: No, hits=0.0 tagged_above=0.0 required=5.0 tests= X-Spam-Level: X-Archive-Number: 200404/259 X-Sequence-Number: 17634 Hi! We have a complex problematic area. What is the simplest solution for the next query type: SELECT * FROM tablename ORDER BY col1 ASC, col2 DESC; In our experience, postgres cannot use a multi-colum index on (col1, col2) in this situation, becouse there are different directions after ORDER BY. Is custom operator class the easiest solution, which can solve the reverse indexing on col2? Our problem with this solution, is that we have to replace "DESC" with "USING myoperator". Is it possible, that postgres can recognize "myoperator" without replacing "DESC"? We made new operators on int4 type starting with letter "/": CREATE OPERATOR CLASS int4_reverse_order_ops FOR TYPE int4 USING btree AS OPERATOR 1 /< , OPERATOR 2 /<= , OPERATOR 3 /= , OPERATOR 4 />= , OPERATOR 5 /> , FUNCTION 1 int4_reverse_order_cmp(int4, int4); Create an index: CREATE INDEX idx_test ON tablename (col1, col2 int4_reverse_order_ops); Postgres can use this index in this query: EXPLAIN SELECT * FROM tablename ORDER BY col1 ASC, col2 USING /< limit 10; QUERY PLAN ------------------------------------------------------------------------ ------------ Limit (cost=0.00..0.52 rows=10 width=8) -> Index Scan using idx_test on tablename (cost=0.00..52.00 rows=1000 width=8) An other problem: we have to replace the operators after the WHERE conditions, if that contains conditions on col2. EXPLAIN SELECT * FROM tablename WHERE col1 < 10 and col2 < 10 ORDER BY col1, col2 using /< limit 10; QUERY PLAN ------------------------------------------------------------------------ ----------- Limit (cost=0.00..4.14 rows=10 width=8) -> Index Scan using idx_test on tablename (cost=0.00..46.33 rows=112 width=8) Index Cond: (col1 < 10) Filter: (col2 < 10) You can see, it use filtering on col2, but in the next case it can indexing on col2 condition: EXPLAIN SELECT * FROM tablename WHERE col1 < 10 and col2 /< 10 ORDER BY col1, col2 using /< limit 10; QUERY PLAN ------------------------------------------------------------------------ ----------- Limit (cost=0.00..3.82 rows=10 width=8) -> Index Scan using idx_test on tablename (cost=0.00..42.78 rows=112 width=8) Index Cond: ((col1 < 10) AND (col2 /< 10)) Can we do this easier? If can, how? After that, we have an other unsolved problem, if the col2's type is TEXT, and we try to use a LIKE operator on it. But we coludn't replace the LIKE with own operator, because postgres exchange the "LIKE" with an expression which contains ">=" and "<". We made own like operator: "/~~", but we cannot tell postgres to use our own "/>=" and '/<' operators instead of "/~~". CREATE OPERATOR /~~ ( leftarg = text, rightarg = text, procedure = textlike, commutator = /~~ , negator = !~~ , restrict = scalarltsel, join = scalarltjoinsel ); Thanks in advance.