代码之家  ›  专栏  ›  技术社区  ›  Dave Jarvis James Eichele

使用整数值的日期算法

  •  2
  • Dave Jarvis James Eichele  · 技术社区  · 15 年前

    问题

    字符串串联正在减慢查询速度:

    date(extract(YEAR FROM m.taken)||'-1-1') d1,
    date(extract(YEAR FROM m.taken)||'-1-31') d2
    

    这是作为字符串的一部分在代码中实现的,字符串如下(其中 p_ 变量是整数,由最终用户输入):

    date(extract(YEAR FROM m.taken)||''-'||p_month1||'-'||p_day1||''') d1,
    date(extract(YEAR FROM m.taken)||''-'||p_month2||'-'||p_day2||''') d2
    

    查询的总运行时间小于10秒;我希望把整个查询时间缩短到2或3秒左右。硬件升级已经发生。;-)

    PostgreSQL 8.4.4。

    创建日期的更好方法是什么(可能没有连接)?

    这看起来很有希望: PGTYPESdate_mdyjul

    3 回复  |  直到 15 年前
        1
  •  1
  •   BenMorel Manish Pradhan    11 年前

    真 的。我很惊讶,但是使用 this page

    postgres=# select to_date(a,1,3) 
    postgres-# from generate_series(100,1000000) as v(a);
    
    Time: 1365.851 ms
    
    postgres=# select (a::text||'-01-03')::date from 
    postgres-# generate_series(100,1000000) as v(a);
    
    Time: 3454.224 ms
    

    完整解决方案

    编辑 dateserial.c

    #include "postgres.h"
    #include "utils/date.h"
    #include "utils/nabstime.h"
    
    #ifdef PG_MODULE_MAGIC
    PG_MODULE_MAGIC;
    #endif
    
    Datum dateserial(PG_FUNCTION_ARGS);
    
    PG_FUNCTION_INFO_V1 (dateserial);
    
    Datum
    dateserial(PG_FUNCTION_ARGS) {
      int32 p_year = PG_GETARG_INT32(0);
      int32 p_month = PG_GETARG_INT32(1);
      int32 p_day = PG_GETARG_INT32(2);
    
      PG_RETURN_DATEADT( date2j( p_year, p_month, p_day ) - POSTGRES_EPOCH_JDATE );
    }
    

    编辑 Makefile :

    MODULES = dateserial
    PGXS := $(shell pg_config --pgxs)
    include $(PGXS)
    

    编辑 inst.sh

    #!/bin/bash
    
    make clean && make && strip *.so && make install && /etc/init.d/postgresql-8.4 restart
    

    bash inst.sh .

    dateserial :

    CREATE OR REPLACE FUNCTION dateserial(integer, integer, integer)
      RETURNS date AS
    '$libdir/dateserial', 'dateserial'
      LANGUAGE 'c' IMMUTABLE STRICT
      COST 1;
    ALTER FUNCTION dateserial(integer, integer, integer) OWNER TO postgres;
    

    测试功能:

    SELECT dateserial( 2007::int, 5, 5 )
    
        2
  •  2
  •   leonbloy    15 年前

    是的,坦白说,我不喜欢Postgresql在这里的做法。似乎大多数日期操作都必须通过将日期字段提取为整数、将其转换为文本、将其附加到更多文本以创建日期的文本表示形式,然后告诉postgres将该文本解析为日期。。。这对我来说很糟糕,我觉得通过解析字符串来构建日期只能通过文本输入来完成。但是,我认为,postgresql将处理文本表示的数据类型联系得太紧密了。所以,举个例子,如果我想用三个整数值(D,M,Y)来构建一个日期,我必须(如果我没弄错的话)构建一个字符串并让PG解析它。我觉得这样做很不干净。。。

    再说,我怀疑这会拖慢你的表演。

        3
  •  0
  •   Dave Jarvis James Eichele    15 年前

    另一种选择是创建 function index