2014-07-10 23 views
1

我不能相信我用带有ORDER BY子句的简单选择看到的。 这里是我的查询和故障结果:Postgresql 9.2对索引字段的时间戳排序不会在一天内的小时部分排序

SELECT date_valid, id_variable FROM myTable 
    WHERE id_stn='78224' AND date_valid BETWEEN '2014-07-03 09:00:00' 
     AND '2014-07-03 21:00:00' AND id_variable IN (11012,12004) 
    ORDER BY date_valid ; 

    date_valid  | id_variable 
---------------------+------------- 
2014-07-03 09:00:00 |  11012 
2014-07-03 15:00:00 |  11012 
2014-07-03 21:00:00 |  11012 
2014-07-03 09:00:00 |  12004 
2014-07-03 15:00:00 |  12004 
2014-07-03 21:00:00 |  12004 

正如你看到的,排序似乎对id_variable而不是date_valid完成。为了得到预期的结果,我要创建一个新的领域PostgreSQL所不能优化或给予的超过1天的时间戳范围:

SELECT date_valid,id_variable FROM myTable 
     WHERE id_stn='78224' AND date_valid BETWEEN '2014-07-03 09:00:00' 
      AND '2014-07-03 21:00:00' AND id_variable IN (11012,12004) 
     ORDER BY date_valid + '0 hours'::INTERVAL; 

    date_valid  | id_variable 
---------------------+------------- 
2014-07-03 09:00:00 |  11012 
2014-07-03 09:00:00 |  12004 
2014-07-03 15:00:00 |  11012 
2014-07-03 15:00:00 |  12004 
2014-07-03 21:00:00 |  11012 
2014-07-03 21:00:00 |  12004 

这里是部分表定义,它partitionned上date_valid为每个月:

Column  |   Type 
---------------+----------------------------- 
id_obs  | bigint      
date_valid | timestamp without time zone 
id_variable | integer 
id_stn  | character varying(50) 
Indexes: 
    "myTable_pkey" PRIMARY KEY, btree (id_obs) 
    "myTable_ukey" UNIQUE CONSTRAINT, btree (date_valid, id_variable, lat, lon) 
Check constraints: 
    "myTable_date_valid_check" CHECK (date_valid >= '2014-07-01 00:00:00'::timestamp without time zone AND date_valid < '2014-08-01 00:00:00'::timestamp without time zone) 
Triggers: 
    myTable_before_update BEFORE UPDATE ON myTable_201407 FOR EACH ROW EXECUTE PROCEDURE obs_update() 
Inherits: myTable_parent 
Has OIDs: no 

这似乎是一个错误,如果结果是在同一天Postgresql不排序小时。它必须是优化器的问题,因为我不要有这个问题,如果我排序在另一个未索引的时间戳字段。如果我在每个日期字符串之后指定:: TIMESTAMP,或者如果我用另一个选项包含在SELECT中,则结果相同(未排序):SELECT * FROM(SELECT ...)x ORDER BY DATE_VALID。我与其他具有相似结构的表格有同样的问题。

这是从PostgreSQL 9.2.8的EXPLAIN结果:

Result (cost=0.02..62864.86 rows=10 width=87) 
    -> Merge Append (cost=0.02..62864.86 rows=10 width=87) 
     Sort Key: myTable.date_valid 
     -> Sort (cost=0.01..0.02 rows=1 width=220) 
       Sort Key: myTable.date_valid 
       -> Seq Scan on myTable (cost=0.00..0.00 rows=1 width=220) 
        Filter: ((date_valid >= '2014-07-03 09:00:00'::timestamp without time zone) AND (date_valid <= '2014-07-03 21:00:00'::timestamp without time zone) AND (id_variable = ANY ('{11012,12004}'::integer[])) AND ((id 
_stn)::text = '78224'::text)) 
     -> Index Scan using myTable_201407_ukey on myTable_201407 myTable (cost=0.00..62864.71 rows=9 width=72) 
       Index Cond: ((date_valid >= '2014-07-03 09:00:00'::timestamp without time zone) AND (date_valid <= '2014-07-03 21:00:00'::timestamp without time zone) AND (id_variable = ANY ('{11012,12004}'::integer[]))) 
       Filter: ((id_stn)::text = '78224'::text) 
+0

PostgreSQL 9.2.0 –

+0

我无法在9.1,9.2或9.3中重现此行为。 –

+4

[9.2.1修复:_Fix可能对涉及WHERE indexed_column IN(list_of_values)_ _(http://www.postgresql.org/docs/9.2/static/release-9-2-1.html ) –

回答

1

大概固定在9.2.1此错误

修正输出的可能的不正确的排序从涉及WHERE indexed_column IN(list_of_values查询)

http://www.postgresql.org/docs/9.2/static/release-9-2-1.html

9.2已经在9.2.8

+0

感谢您的帮助,但并未解决问题。更新到9.2.8,重新索引了所有的数据库并仍然得到相同的结果。但是,这是一个很好的线索,就像我用“(id_variable = 11012或id_variable = 12004)”替换“id_variable IN(11012,12004)”一样,顺序是OK(在更新之前和之后测试)。 –

+0

@LeDroid更新后是否重新启动服务器? –

+0

Postgresql服务器完全停止,但我没有重新启动硬件,因为Postgresql没有运行任何东西。你认为这是必要的吗? –