【问题标题】:Enterprise Postgresql Query performance on millions of rows数百万行的 Enterprise Postgresql 查询性能
【发布时间】:2018-12-26 08:04:47
【问题描述】:

请查找以下过程。游标(cntry_lobreg_lang_cur)包含 23749782 行,视图(技能)包含 629 行。加入和检索行需要 3 个多小时。它使用 100% CPU(8 核)和内存(64GB)并崩溃。

请您建议如何提高性能。

 CREATE TYPE lang_tab AS ( countryid character varying(255), lob_id character varying(255), region_id numeric(10,0), language_id character varying(255), roleid character varying(255), language_id_flag character varying(5), roleid_flag character varying(5), course_id character varying(255), skill_id character varying(255), language_id_null character varying(5), roleid_null character varying(5), lob_name character varying(256) );

CREATE TYPE lang_obj AS lang_tab;


DECLARE
    CURSOR cntry_lobreg_lang_cur is
        SELECT *
        FROM
               LOBREG_LANGROLE
        ;

    _array_type lang_obj := lang_obj();
BEGIN

    OPEN cntry_lobreg_lang_cur;
    LOOP
        FETCH cntry_lobreg_lang_cur BULK COLLECT
        INTO  _array_type LIMIT 30000
        ;

        EXIT WHEN _array_type.count = 0;
        dbms_output.put_line('_array_type : '
        ||_array_type.COUNT);

        INSERT        INTO LANGROL_TAB
               (COUNTRYID
                    , LOB_ID
                    , REGION_ID
                    , LANGUAGE_ID
                    , ROLEID
                    , SKILL_ID
                    , LOB_NAME
               )
        SELECT
               A.COUNTRYID
             , A.LOB_ID
             , A.REGION_ID
             , A.LANGUAGE_ID
             , A.ROLEID
             , B.PRODUCTID
             , A.LOB_NAME
        FROM
               TABLE(_array_type) A
             , skills             B
        WHERE
               A.LOB_NAME=B.LINE_OF_BUSINESS
        ;

    END LOOP;

    CLOSE cntry_lobreg_lang_cur;

END;

如果您有任何疑问,请告诉我。

【问题讨论】:

  • 样本数据和期望的结果会有所帮助。
  • 完全不需要使用游标的逐个缓慢的方法。这种方法总是比使用单个 insert into ... select 语句慢很多

标签: sql plpgsql query-performance postgresql-9.5 sqlperformance


【解决方案1】:

首先将逻辑重写为单个语句:

INSERT INTO LANGROL_TAB (COUNTRYID, LOB_ID, REGION_ID, LANGUAGE_ID, ROLEID, SKILL_ID, LOB_NAME)
    SELECT l.COUNTRYID, l.LOB_ID, l.REGION_ID, l.LANGUAGE_ID, l.ROLEID,
           B.PRODUCTID,
           l.LOB_NAME
    FROM LOBREG_LANGROLE l JOIN
         skills s
         ON l.LOB_NAME = s.LINE_OF_BUSINESS;

然后,如果您没有,请在skills(LINE_OF_BUSINESS, PRODUCTID) 上添加索引。

注意事项:

  • 避免使用光标。
  • 始终使用明确、正确、标准 JOIN 语法。 从不FROM 子句中使用逗号。
  • 使用有意义的表别名。 ab 没有任何意义;表名的缩写。

【讨论】:

    猜你喜欢
    • 2023-01-05
    • 2018-01-01
    • 2012-07-10
    • 1970-01-01
    • 2013-11-27
    • 2010-09-14
    • 2017-10-01
    • 2016-05-02
    • 1970-01-01
    相关资源
    最近更新 更多