2

複数の週テーブルから単位を読み取る必要がある SQL (postgresql) の関数があります (最大単位数と最大週数)。

単位は、別のテーブルで定義されているいくつかのテーブル (類似) にあります。各テーブルには 22,000,000 を超えるユニットがあります。

いくつかのケースでは、必要なものに十分な単位を取得するために複数のテーブルを検索する必要がありますが、1 つしか必要ない場合もあります。

基本的に、特定の店舗の直近の週からの大きなサンプルが必要です。

現在、次のものがあります。

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、一時テーブルを削除しますか? 大きな変化をもたらす何か。

4

1 に答える 1