我们在 SQL (postgresql) 中有一个函数,它需要从多个周表中读取单位(最多为单位和最多周)。
这些单位在另一个表中定义的几个表(类似)中。每个表有 > 22,000,000 个单位。
在某些情况下,我们需要搜索多个表以获得足够的单位来满足我们的需要,但在其他一些情况下,我们可能只需要一个。
基本上,我们需要给定商店最近几周的大样本。
我们目前有:
CREATE OR REPLACE FUNCTION get_units(_cursor REFCURSOR,
_obs_time timestamp without time zone,
_unit_store integer, _unit_limit integer,
_week_limit integer) RETURNS REFCURSOR
LANGUAGE plpgsql
AS $BODY$
DECLARE
_week_cursor REFCURSOR;
_table_name TEXT;
_query_sql TEXT;
_command TEXT := '(SELECT ''0001-01-01'' AS obs_time,
0::smallint detail
WHERE FALSE)';
_week_count INTEGER;
_result_count INTEGER := 0;
_current_unit_limit INTEGER;
BEGIN
OPEN _week_cursor FOR
SELECT table_name
FROM week_table
WHERE create_time < _obs_time
ORDER BY create_time desc
LIMIT _week_limit;
_current_unit_limit := _unit_limit;
LOOP
FETCH _week_cursor INTO _table_name;
EXIT WHEN NOT FOUND;
_query_sql :=
'FROM ' || _table_name || ' u
WHERE u.unit_store = ' || _unit_store || ' ';
EXECUTE 'SELECT count(*) ' || _query_sql || ' LIMIT ' || _current_unit_limit INTO _week_count;
_result_count := _result_count + _week_count;
_current_unit_limit := _unit_limit - _result_count;
IF _week_count > 0 THEN
_command := _command || ' UNION ALL
(SELECT u.obs_time obs_time,
u.detail detail '
|| _query_sql
|| ' ORDER BY u.obs_time DESC'
|| ' LIMIT ' || _week_count || ')';
END IF;
IF (_result_count >= _unit_limit) THEN
EXIT;
END IF;
END LOOP;
CLOSE _week_cursor;
OPEN _cursor FOR EXECUTE _command;
RETURN _cursor;
END;
$BODY$;
在大多数情况下,结果都很好,但在一些最坏的情况下(几个星期,每个只有很少的记录),我们的速度会变慢。
有什么建议可以改进以及如何改进?例如,删除 UNION ALL 临时表?会产生重大变化的东西。