Informix SPL功能“有点”变种?

时间:2013-12-03 21:31:53

标签: informix

Informix 10.0 SPL函数在VARIANTNOT VARIANT之间是否存在某种中间立场?

我是Informix的新手。我在Informix 10.0中有一个SPL函数get_timezone_offset,用于计算给定时区是否在夏令时内以及生成的UTC偏移量(下面发布的代码)。

在大型表的WHERE子句中使用此函数(> 1M记录)对时间戳字段,需要几分钟才能完成:

select count(*)
from Table
where Table.startDateTime >= current - (get_timezone_offset('et') units hour) - 1 units day

没有该函数调用的相同查询是<1秒长:

select count(*)
from Table
where Table.startDateTime >= current - 1 units day

我认为差异来自于查询优化器能够将current - 1 units day“简化”为常量;我可以使用get_timezone_offset修改alter function get_timezone_offset with (add not variant)函数,然后包含函数调用的第一个查询只需不到一秒钟即可完成。但我的功能实际上是每年两次更改输出相同的输入,所以它不是not variant

如何让优化器仅在查询期间将我的函数视为常量?

create procedure get_timezone_offset(timezone varchar(8))
    returning decimal as "current timezone offset";
-- This SQL calculates the current timezone's offset from UTC based on whether
-- the given timezone is in Daylight Saving Time right now or not.
-- DST is assumed to begin at 2:00 AM (in the given timezone) on the second
-- Sunday of March, and to end at 2:00 AM (in the given timezone, accounting for
-- DST) on the first Sunday of November.
-- Specify the timezone by giving a string for timezone which will correspond
-- to what's in the timezone_offsets table.

define offset decimal;

select
    "current timezone offset"
into offset
from (
    select
        "time (utc)",
        "in daylight savings time",
        "standard timezone offset",
        -- When we're in DST then the timezone offset from UTC increases by one
        case
            when "in daylight savings time" then "standard timezone offset" + 1
            else "standard timezone offset"
        end as "current timezone offset"
    from (
        select
            "time (utc)",
            -- Knowing when we currently are in relation to when the DST
            -- "triggers" are makes it easy to determine if we're in DST or not
            case
                when "time (utc)" >= "march trigger (utc)" and "time (utc)" < "november trigger (utc)" then 't'::boolean
                else 'f'::boolean
            end as "in daylight savings time",
            "standard timezone offset"
        from (
            select
                "time (utc)",
                -- DST begins at 2:00AM on the second Sunday in March. For
                -- Eastern Time, for example, that will be at 7:00 AM UTC
                mdy(3, "second sunday in march", year("time (utc)"))::datetime year to hour + ((2 - "standard timezone offset") units hour) as "march trigger (utc)",
                -- DST ends at 2:00AM on the first Sunday in November. For
                -- Eastern Time, for example, that will be at 6:00 AM UTC
                mdy(11, "first sunday in november", year("time (utc)"))::datetime year to hour + ((1 - "standard timezone offset") units hour) as "november trigger (utc)",
                "standard timezone offset"
            from (
                select
                    "time (utc)",
                    "standard timezone offset",
                    -- Figure out when the second Sunday in March and the first
                    -- Sunday in November are in UTC time
                    mod((7 - weekday(mdy(3, 1, year("time (utc)")))), 7) + 8 as "second sunday in march",
                    mod((7 - weekday(mdy(11, 1, year("time (utc)")))), 7) + 1 as "first sunday in november"
                from (
                    -- Get the timezone's UTC offset for when the timezone is in
                    -- standard time. Also get the current UTC time for later
                    -- calculations
                    select
                        "standard_utc_offset" as "standard timezone offset",
                        ('1970-01-01 00:00:00'::datetime year to second) + ((dbinfo('utc_current') / (60)) units minute) as "time (utc)"
                    from timezone_offsets
                    where timezone_offsets.timezone = timezone
                )
            )
        )
    )
);

return offset;

end procedure

2 个答案:

答案 0 :(得分:1)

非变量意味着对于给定的输入,无论如何输出总是相同的。这允许引擎魔术。你可能最好使用两个函数,一个返回时区信息,一个返回夏令时调整 - 这两个函数都是非变量。

您的功能仅适用于美国AFAIC,ROW使用第13周和第43周进行更改

答案 1 :(得分:1)

嗯......正式你是对的......功能是VARIANT。但我认为你回答了这个问题......你问的是引擎在查询期间如何将其视为非VARIANT ......如果你将它设置为NOT VARIANT,你就会完全按照你的意思行事。如果查询在DST更改之前开始并在DST更改之后结束,则它只会返回错误的结果。对于运行时间少于1秒的查询以及每年发生两次onloy的事件,我会说你很安全,但这是你需要定义的。

除了这些考虑之外,你说的一切都是真的。这是调用函数1次或1M次之间的区别......调用SPL很慢(与C函数等其他选项相比)。

问候。