Re: Memory use in 8.3 plpgsql with heavy use of xpath()

Поиск
Список
Период
Сортировка
От Matt Magoffin
Тема Re: Memory use in 8.3 plpgsql with heavy use of xpath()
Дата
Msg-id 50987.192.168.1.108.1214982055.squirrel@msqr.us
обсуждение исходный текст
Ответ на Re: Memory use in 8.3 plpgsql with heavy use of xpath()  (Tom Lane <tgl@sss.pgh.pa.us>)
Ответы Re: Memory use in 8.3 plpgsql with heavy use of xpath()  (Tom Lane <tgl@sss.pgh.pa.us>)
Список pgsql-general
>> OK, I'll try to come up with something. Do you have a recommended way of
>> capturing the amount memory being used by Postgres related to this? I
>> was
>> thinking I would have a plpgsql function that loops a large number of
>> times, calling a few xpath() calls,
>
> Yeah, that's what I'd try first.
>
>             regards, tom lane

Below is a test case that simulates the use of xpath() within a plpgsql
function in my application. I'm not sure of a good way to measure the
retained memory before/after the script runs, however. I ran this several
times and the postgres process that ran it does have more memory allocated
afterwards than before, but I don't know what is expected and what isn't.

You can adjust the number of loops that run at

    num_loops int8 := 1000000;

-- m@

-----
DROP TABLE IF EXISTS tmp_xml_test CASCADE;
DROP TABLE IF EXISTS tmp_xml_addr CASCADE;
CREATE TEMPORARY TABLE tmp_xml_test(
    id int4, x xml, primary key (id));
CREATE TEMPORARY TABLE tmp_xml_addr(
    id int4, xmlpos int4, street text, city text, state text, zip text,
    primary key (id, xmlpos));

CREATE OR REPLACE FUNCTION tmp_extract_address(data_row tmp_xml_test)
RETURNS void AS
$BODY$
DECLARE
    addr_row tmp_xml_addr%ROWTYPE;
    tmp_txt text;
    tmp_array xml[];
BEGIN
    addr_row.id := data_row.id;
    DELETE FROM tmp_xml_addr WHERE id = data_row.id;
    tmp_array := xpath(
        '/po:purchaseOrder/*[name(.) = "shipTo" or name(.) =  "billTo"]',
        data_row.x, ARRAY[ARRAY['po', 'http://www.example.com/PO1']]);
    IF array_upper(tmp_array, 1) > 0 THEN
        FOR idx IN 1..array_upper(tmp_array, 1) LOOP
            addr_row.xmlpos := idx;
            addr_row.street := upper(XMLSERIALIZE(CONTENT(xpath(
                '/po:purchaseOrder/*[name(.) = "shipTo" or name(.) =  "billTo"]['
                ||idx|| ']/po:street[1]/text()',
                data_row.x, ARRAY[ARRAY['po', 'http://www.example.com/PO1']]))[1] as
text));
            addr_row.city := upper(XMLSERIALIZE(CONTENT(xpath(
                '/po:purchaseOrder/*[name(.) = "shipTo" or name(.) =  "billTo"]['
                ||idx|| ']/po:city[1]/text()',
                data_row.x, ARRAY[ARRAY['po', 'http://www.example.com/PO1']]))[1] as
text));
            addr_row.state := upper(XMLSERIALIZE(CONTENT(xpath(
                '/po:purchaseOrder/*[name(.) = "shipTo" or name(.) =  "billTo"]['
                ||idx|| ']/po:state[1]/text()',
                data_row.x, ARRAY[ARRAY['po', 'http://www.example.com/PO1']]))[1] as
text));
            addr_row.zip := upper(XMLSERIALIZE(CONTENT(xpath(
                '/po:purchaseOrder/*[name(.) = "shipTo" or name(.) =  "billTo"]['
                ||idx|| ']/po:zip[1]/text()',
                data_row.x, ARRAY[ARRAY['po', 'http://www.example.com/PO1']]))[1] as
text));
            INSERT INTO tmp_xml_addr (id, xmlpos, street, city, state, zip) VALUES
                (addr_row.id, addr_row.xmlpos, addr_row.street, addr_row.city,
                addr_row.state, addr_row.zip);
        END LOOP;
    END IF;
    RETURN;
END;
$BODY$
LANGUAGE 'plpgsql';

CREATE OR REPLACE FUNCTION tmp_populate_addr() RETURNS trigger AS
$BODY$
BEGIN
    PERFORM tmp_extract_address(NEW);
    RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql';

CREATE TRIGGER tmp_populate_addr_trigger AFTER INSERT OR UPDATE ON
tmp_xml_test
FOR EACH ROW EXECUTE PROCEDURE tmp_populate_addr();

DROP FUNCTION IF EXISTS tmp_test_loop();
CREATE OR REPLACE FUNCTION tmp_test_loop() RETURNS SETOF tmp_xml_addr AS
$BODY$
DECLARE
    num_loops int8 := 1000000;
BEGIN
    FOR idx IN 1..num_loops LOOP
        INSERT INTO tmp_xml_test VALUES (idx,
$$<purchaseOrder xmlns="http://www.example.com/PO1" orderDate="1999-10-20">
   <shipTo country="US">
      <name>Alice Smith</name>
      <street>123 Maple Street</street>
      <city>Mill Valley</city>
      <state>CA</state>
      <zip>90952</zip>
   </shipTo>
   <billTo country="US">
      <name>Robert Smith</name>
      <street>8 Oak Avenue</street>
      <city>Old Town</city>
      <state>PA</state>
      <zip>95819</zip>
   </billTo>
   <comment>Hurry, my lawn is going wild!</comment>
   <items>
      <item partNum="872-AA">
         <productName>Lawnmower</productName>
         <quantity>1</quantity>
         <USPrice>148.95</USPrice>
         <comment>Confirm this is electric</comment>
      </item>
      <item partNum="926-AA">
         <productName>Baby Monitor</productName>
         <quantity>1</quantity>
         <USPrice>39.98</USPrice>
         <shipDate>1999-05-21</shipDate>
      </item>
   </items>
</purchaseOrder>$$);
    END LOOP;
    FOR idx IN 1..num_loops LOOP
        UPDATE tmp_xml_test SET id = idx WHERE id = idx;
    END LOOP;
    RETURN QUERY SELECT * FROM tmp_xml_addr ORDER BY id, xmlpos;
END;
$BODY$
LANGUAGE 'plpgsql';

SELECT * FROM tmp_test_loop();



В списке pgsql-general по дате отправления:

Предыдущее
От: Klint Gore
Дата:
Сообщение: pg_dump - lost synchronization with server: got message type "d", length 6036499
Следующее
От: Magnus Hagander
Дата:
Сообщение: Re: Target lists can have at most 1664 entries?