【问题标题】:PostgresSQL Function takes long timePostgresQL 函数需要很长时间
【发布时间】:2020-08-04 07:35:39
【问题描述】:

我有一个 PostgresSQL 函数:

CREATE OR REPLACE FUNCTION public.replace_id_special_char(my_suf text)
    RETURNS text
    LANGUAGE 'plpgsql'

    COST 100
    VOLATILE 
AS $BODY$
                    declare 
                        c1          text;
                        c2          text;
                        cursor1     refcursor;      
                        lc_time     time with time zone;
                    begin                       
                            open cursor1 for execute 'SELECT column_name,data_type from information_schema.columns WHERE column_name not in(''qr_id'',''qr_nm'',''qr_op_id'',''qr_op_nm'',''qr_op_line_seq'',''date_start'',''date_end'',''qr_op_val_seq'',''qr_op_value'') AND table_name = lower(''tmp_qw_'||$1||''') AND table_schema =current_schema()';                                                
                            loop        
                                fetch cursor1 into c1,c2;
                                exit when not found;
                                raise notice 'column_name: %', c1;
                                if upper(c2)=upper('text') then

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id1__'',''!'')';

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id2__'',''@'')';

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id3__'',''#'')';

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id4__'',''$'')';

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id5__'',''%'')';

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id6__'',''^'')';

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id7__'',''&'')';

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id8__'',''*'')';

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id9__'',''('')';

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id10__'','')'')';

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id11__'',''-'')';

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id12__'',''='')';

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id13__'',''+'')';

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id14__'',''"'')';

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id15__'',''\'')';

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id16__'',''.'')';

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id17__'',''/'')';

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id18__'','' '')';

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id19__'','':'')';

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id20__'','''')';

                                    execute'update tmp_qw_'||$1||' set '||c1||'=replace('||c1||',''__id0__'','''')';
                                end if;
                            end loop;
                            close cursor1;  
                            return 'values replaced.';  
                    end; $BODY$;

我正在运行超过 27 个查询。此功能需要很长时间才能运行。有什么方法可以加快速度吗?

【问题讨论】:

  • 试过PREPARE那些EXECUTEs?
  • 另外,应该添加一些过滤条件,以便不是所有的行都被更新,只是那些需要的......
  • 准备会影响时间吗?

标签: postgresql


【解决方案1】:

与其运行 27 个大型 UPDATEs,不如运行一个这样的

UPDATE ...
SET ... = replace(
             ...
             replace(
                replace(
                   ..., '__id1__','!'
                ), '__id2__', '@'
             ), ...
          )
FROM ...
WHERE ... LIKE '%\_\_id_\_\_%';

此外,您的函数容易受到 SQL 注入的影响。使用format() 正确格式化查询字符串中的标识符和字符串文字:

EXECUTE format(
           'update %I set %I = ...',
           'tmp_qw_' || $1,
           c1
        );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-07
    相关资源
    最近更新 更多