0

XML を出力する PL/PGsql ストアド プロシージャで問題が発生しました。

基本的には、クエリの結果をxmlとして出力する関数です。

クエリは十分に高速ですが、結果のセットが大きくなりすぎると、xmlconcat がますます遅くなることがわかりました。

機能を簡略化した内容です。

CREATE OR REPLACE FUNCTION test_function (v_limit int)
    RETURNS xml AS
$BODY$
DECLARE
    v_rec record;
    v_xml xml;
    v_query text;
BEGIN

    v_query := 'SELECT * FROM test_table LIMIT ' || v_limit;

    FOR v_rec IN EXECUTE v_query LOOP

        v_xml := xmlconcat(v_xml,
                     xmlelement(name content, v_rec.content)
                 );

    END LOOP;

    RETURN v_xml ;
END
$BODY$
    LANGUAGE 'plpgsql' SECURITY DEFINER ;

テーブル test_table には、テキスト型の content という名前のフィールドだけが含まれています。コンテンツの平均の長さは 100 文字です。

この問題は、連結するレコードが大量にある場合に発生します。

この説明分析を見てください。必要な時間は指数関数的に増加します。

db=# explain analyze select test_function(500);
                                      QUERY PLAN
--------------------------------------------------------------------------------------
 Result  (cost=0.00..0.26 rows=1 width=0) (actual time=42.890..42.893 rows=1 loops=1)
 Total runtime: 42.909 ms
(2 rows)


db=# explain analyze select test_function(1000);
                                       QUERY PLAN
----------------------------------------------------------------------------------------
 Result  (cost=0.00..0.26 rows=1 width=0) (actual time=109.153..109.159 rows=1 loops=1)
 Total runtime: 109.178 ms
(2 rows)

db=# explain analyze select test_function(10000);
                                        QUERY PLAN
------------------------------------------------------------------------------------------
 Result  (cost=0.00..0.26 rows=1 width=0) (actual time=8304.257..8304.277 rows=1 loops=1)
 Total runtime: 8304.298 ms
(2 rows)

xmlconcat を使用しない単一のクエリのコストは、10000 レコードに対してわずか 36 ミリ秒です。

xmlconcat の効率を改善するための提案はありますか?

サーバーのバージョンは 8.3.6 です... xmlagg 機能を利用できません

4

3 に答える 3

0

この関数をテストしてみてください:

CREATE OR REPLACE FUNCTION test_function (v_limit int)
    RETURNS xml AS
$BODY$
BEGIN
    RETURN SELECT xmlagg(xmlelement(name content, tt.content))
           FROM test_table tt 
           LIMIT v_limit;
END
$BODY$
    LANGUAGE 'plpgsql' SECURITY DEFINER ;
于 2012-12-04T09:23:24.120 に答える
0

この種のメモリの問題は、XML でよく見られます。これは、DOMparser の使用に関連していることがよくあります。DOMparser は完全なドキュメントをメモリに保持します。これは、ドキュメントを集中的に処理する場合に非常に便利です。

別の理由として、古いオブジェクトが適切にクリーンアップされていないことが考えられます。ドキュメントの解析により多くの一時オブジェクトが作成されるため、パフォーマンスが低下する原因になることもありました。

XMLconcat は、毎回すべてのパラメーターを解析する場合があります。コードの処理中に上記の問題の 1 つだけが存在する場合、処理はますます遅くなります。

これらの問題の原因を正確に理解するには、xmlconcat のコードを詳しく調べる以外に不可能です。しかし、必要なのは一連の xml 要素を連結することだけです。xmlconcat の使用は、おそらく予測可能な状況に対して複雑すぎるため、やり過ぎかもしれません。xmlconcat の使用をやめて、自分で連結を書き始めることをお勧めします。同時に最速かつ最も適切なソリューションかもしれません。

于 2012-12-04T13:25:07.937 に答える
0

postgresql 11 の xmlagg のパフォーマンスは同じですが、string_agg に簡単に置き換えることができます。いくつかのテスト:

select xmlagg(xmlelement(name "id", s.id)) el
from generate_series(1, 10000) s(id)
- Execution Time: 131.849 ms

select xmlagg(xmlelement(name "id", s.id)) el
from generate_series(1, 20000) s(id)
- Execution Time: 623.741 ms

select xmlagg(xmlelement(name "id", s.id)) el
from generate_series(1, 30000) s(id)
- Execution Time: 1571.545 ms

select string_agg(xmlelement(name "id", s.id)::text, '')::xml el
from generate_series(1, 10000) s(id)
- Execution Time: 38.743 ms

select string_agg(xmlelement(name "id", s.id)::text, '')::xml el
from generate_series(1, 20000) s(id)
- Execution Time: 54.399 ms

select string_agg(xmlelement(name "id", s.id)::text, '')::xml el
from generate_series(1, 30000) s(id)
- Execution Time: 91.766 ms
于 2019-11-06T15:22:54.480 に答える