带有时间戳的可选过程非常慢

时间:2019-03-10 17:33:39

标签: sql stored-procedures firebird

我有以下选择语句:

SELECT
    "TRIP"."ID" as "ID",
    "TRIP"."KEY" as "TRIP_KEY",
    "ROUTE"."KEY" as "ROUTE_KEY",
    "ROUTE"."AGENCY_ID" as "AGENCY_ID",
    "TRIP"."BLOCK" as "BLOCK",
    "TRIP"."DIRECTION" as "DIRECTION",
    "CALENDAR"."MASK" as "MASK",
    "CALENDAR"."START_DATE",
    "CALENDAR"."END_DATE",
    "TRIP"."CALENDAR_ID" as "CALENDAR_ID"
    FROM "STOP_TIME" 
    JOIN "FEED" ON("STOP_TIME"."FEED_ID"="FEED"."ID") 
    JOIN "TRIP" ON ("STOP_TIME"."TRIP_ID"="TRIP"."ID") 
    JOIN "CALENDAR" ON("TRIP"."CALENDAR_ID"="CALENDAR"."ID") 
    JOIN "ROUTE" ON("TRIP"."ROUTE_ID"="ROUTE"."ID")
WHERE 
    "FEED"."REALTIME_FEED"='TrainFeed' AND 
    "FEED"."ACTIVE" = true AND 
    "CALENDAR"."START_DATE" <= '15.03.2019 11:00' AND 
    "CALENDAR"."END_DATE" >= '10.03.2019 11:00' AND
    "STOP_TIME"."DEPARTURE_TIME" >= 0 AND 
    "STOP_TIME"."DEPARTURE_TIME" < 39600000

这给了我以下运行时行为(FlameRobin的输出):

  

执行语句...
  语句已执行(经过的时间:0.000s)。
  4287读取,0个标记,1847个读取,0个写入。
  0次插入,0次更新,0次删除,722个索引,3个序列。
  增量内存:1415008字节。
  总执行时间:0.322s
  脚本执行完成。

但是,如果我将此查询放在可选择的过程中:

SET TERM ^ ;
CREATE PROCEDURE SELECT_TIMETABLE (
    FEEDNAME varchar(100),
    CALENDAR_TIME timestamp,
    TIME_FROM integer,
    TIME_TO integer)
RETURNS (
    ID bigint,
    TRIP_KEY varchar(100),
    ROUTE_KEY varchar(100),
    AGENCY_ID bigint,
    "BLOCK" varchar(100),
    DIRECTION smallint,
    MASK smallint,
    CALENDAR_ID bigint)
AS
DECLARE VARIABLE valid_trip BOOLEAN;
BEGIN 
    FOR SELECT
        "TRIP"."ID" as "ID",
        "TRIP"."KEY" as "TRIP_KEY",
        "ROUTE"."KEY" as "ROUTE_KEY",
        "ROUTE"."AGENCY_ID" as "AGENCY_ID",
        "TRIP"."BLOCK" as "BLOCK",
        "TRIP"."DIRECTION" as "DIRECTION",
        "CALENDAR"."MASK" as "MASK",
        "TRIP"."CALENDAR_ID" as "CALENDAR_ID"
    FROM "STOP_TIME" 
        JOIN "FEED" ON("STOP_TIME"."FEED_ID"="FEED"."ID") 
        JOIN "TRIP" ON ("STOP_TIME"."TRIP_ID"="TRIP"."ID") 
        JOIN "CALENDAR" ON("TRIP"."CALENDAR_ID"="CALENDAR"."ID") 
        JOIN "ROUTE" ON("TRIP"."ROUTE_ID"="ROUTE"."ID")
    WHERE 
        "FEED"."REALTIME_FEED"=:feedName AND 
        "FEED"."ACTIVE" = true AND 
        "CALENDAR"."START_DATE" <= :calendar_time AND 
        "CALENDAR"."END_DATE" >= :calendar_time AND 
        "STOP_TIME"."DEPARTURE_TIME" >= :time_from AND 
        "STOP_TIME"."DEPARTURE_TIME" < :time_to
    INTO :id, :trip_key, :route_key, :agency_id, :block, :direction, :mask, :calendar_id DO 
    BEGIN
        SUSPEND;
    END
END^
SET TERM ;

并使用相同的参数调用它:

SELECT 
    p.ID, p.TRIP_KEY, 
    p.ROUTE_KEY, 
    p.AGENCY_ID, 
    p."BLOCK", 
    p.DIRECTION,
    p.MASK, p.CALENDAR_ID
FROM SELECT_TIMETABLE (
    'TrainFeed', 
    '15.03.2019 11:00', 
    0, 
    39600000) p;

我的运行时行为变得更糟:

  

执行语句...
  语句已执行(经过的时间:0.000s)。
  3248968读取,0个标记,52540个读取,0个写入。
  0插入,0更新,0删除,1338852索引,42序列。
  增量内存:784个字节。
  总执行时间:3.477秒
  脚本执行完成。

我将其范围缩小到了CALENDAR表的START_DATE和END_DATE。如果我省略过滤器,执行时间将减少到半秒。除此之外,上面的可选过程也不会像查询那样给出任何结果(使用START_DATE / END_DATE过滤)。

所以我的可选程序似乎出了点问题。但是我看不到问题。

在Windows上,Firebird版本为3.0.4.33054(x64)。我目前将Firebird用作嵌入式服务器。

0 个答案:

没有答案