• [2023-09-13]使用EXPDP/IMPDP迁移数据库后统计信息引起的性能问题


    问题描述:

            客户在使用expdp/impdp迁移数据库完成后,在新环境收集统计信息,但是在迁移完成的当天中午,好多SQL语句执行变慢,执行计划发生了改变,下面通过案例来说明。

    1、准备数据

    scott用户下创建test表,插入9999行数据,并且把id>2的全部更新成99,这样id列数据就会出现严重倾斜。


    1. conn scott/tiger
    2. drop table test purge;
    3. create table test (id int, name varchar2(20));
    4. insert into test select level lv, dbms_random.string('l',20) from dual connect by level < 10000;
    5. update test set id = 99 where id > 2;
    6. commit;

    2、 根据ID列查询TEST表(这样ID列会记录在col_usage$视图里面)


    1. SQL> select * from test where id = 1;
    2. ID NAME
    3. ---------- ------------------------------------------------------------
    4. 1 whkefbijsvipefdgnoez
    5. SQL>
    6. #####根据test表对应的object_id查询col_usage$视图
    7. SQL> exec DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;
    8. PL/SQL procedure successfully completed.
    9. SQL> select * from col_usage$ where obj# = (select object_id from dba_objects where object_name = 'TEST' and owner='SCOTT');
    10. OBJ# INTCOL# EQUALITY_PREDS EQUIJOIN_PREDS NONEQUIJOIN_PREDS
    11. ---------- ---------- -------------- -------------- -----------------
    12. RANGE_PREDS LIKE_PREDS NULL_PREDS TIMESTAMP
    13. ----------- ---------- ---------- ---------------
    14. 97981 1 1 0 0
    15. 1 0 0 13-SEP-23

    3、对TEST表收集统计信息,统计信息参数都不用写,用默认值


    1. SQL> exec DBMS_STATS.GATHER_TABLE_STATS(ownname=>'SCOTT',tabname=>'TEST');
    2. PL/SQL procedure successfully completed.
    3. SQL>

    4、查看TEST表列的统计信息


    可以看到ID列上面有直方图信息

    1. SQL> set lin 200
    2. SQL> col COLUMN_NAME for a30
    3. SQL> select a.column_name,
    4. 2 b.num_rows,
    5. 3 a.num_distinct distinct_num,
    6. 4 round(a.num_distinct / b.num_rows * 100, 2) selectivity,
    7. 5 a.histogram,
    8. 6 a.num_buckets
    9. 7 from dba_tab_col_statistics a, dba_tables b
    10. 8 where a.owner = b.owner
    11. 9 and a.table_name = b.table_name
    12. 10 and a.owner = 'SCOTT'
    13. 11 and a.table_name = 'TEST';
    14. COLUMN_NAME NUM_ROWS DISTINCT_NUM SELECTIVITY HISTOGRAM NUM_BUCKETS
    15. ------------------------------ ---------- ------------ ----------- --------------------------------------------- -----------
    16. NAME 9999 9999 100 NONE 1
    17. ID 9999 3 .03 FREQUENCY 3
    18. SQL>

    5、导出TEST


    统计信息也一起导出

    1. [oracle@11g ~]$ cat expdp_full_data.par
    2. userid="/ as sysdba"
    3. directory=MY_DIR
    4. dumpfile=expdp_full_data_%U.dmp
    5. logfile=expdp_full_data.log
    6. PARALLEL=16
    7. CLUSTER=N
    8. tables=scott.test
    9. compression=all
    10. [oracle@11g ~]$ expdp parfile=expdp_full_data.par
    11. Export: Release 11.2.0.4.0 - Production on Wed Sep 13 14:57:55 2023
    12. Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
    13. Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
    14. With the Partitioning, OLAP, Data Mining and Real Application Testing options
    15. FLASHBACK automatically enabled to preserve database integrity.
    16. Starting "SYS"."SYS_EXPORT_TABLE_01": /******** AS SYSDBA parfile=expdp_full_data.par
    17. Estimate in progress using BLOCKS method...
    18. Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
    19. Total estimation using BLOCKS method: 384 KB
    20. . . exported "SCOTT"."TEST" 129.0 KB 9999 rows
    21. Processing object type TABLE_EXPORT/TABLE/TABLE
    22. Processing object type TABLE_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
    23. Master table "SYS"."SYS_EXPORT_TABLE_01" successfully loaded/unloaded
    24. ******************************************************************************
    25. Dump file set for SYS.SYS_EXPORT_TABLE_01 is:
    26. /home/oracle/dir/expdp_full_data_01.dmp
    27. /home/oracle/dir/expdp_full_data_02.dmp
    28. Job "SYS"."SYS_EXPORT_TABLE_01" successfully completed at Wed Sep 13 14:58:03 2023 elapsed 0 00:00:06
    29. [oracle@11g ~]$

    6、DROP TEST表


    1. SQL> drop table test purge;
    2. Table dropped.
    3. SQL>

    7、重新导入TEST表


    1. [oracle@11g ~]$ cat impdp_full_data.par
    2. userid="/ as sysdba"
    3. directory=MY_DIR
    4. dumpfile=expdp_full_data_%U.dmp
    5. logfile=impdp_full_data.log
    6. PARALLEL=16
    7. CLUSTER=N
    8. full=y
    9. [oracle@11g ~]$ impdp parfile=impdp_full_data.par
    10. Import: Release 11.2.0.4.0 - Production on Wed Sep 13 15:00:23 2023
    11. Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
    12. Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
    13. With the Partitioning, OLAP, Data Mining and Real Application Testing options
    14. Master table "SYS"."SYS_IMPORT_FULL_01" successfully loaded/unloaded
    15. Starting "SYS"."SYS_IMPORT_FULL_01": /******** AS SYSDBA parfile=impdp_full_data.par
    16. Processing object type TABLE_EXPORT/TABLE/TABLE
    17. Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
    18. . . imported "SCOTT"."TEST" 129.0 KB 9999 rows
    19. Processing object type TABLE_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
    20. Job "SYS"."SYS_IMPORT_FULL_01" successfully completed at Wed Sep 13 15:00:27 2023 elapsed 0 00:00:03
    21. [oracle@11g ~]$

    8、查看TEST表统计信息


    上面还有直方图信息

    1. SQL> set lin 200
    2. SQL> col COLUMN_NAME for a30
    3. SQL> select a.column_name,
    4. 2 b.num_rows,
    5. 3 a.num_distinct distinct_num,
    6. 4 round(a.num_distinct / b.num_rows * 100, 2) selectivity,
    7. 5 a.histogram,
    8. 6 a.num_buckets
    9. 7 from dba_tab_col_statistics a, dba_tables b
    10. 8 where a.owner = b.owner
    11. 9 and a.table_name = b.table_name
    12. 10 and a.owner = 'SCOTT'
    13. 11 and a.table_name = 'TEST';
    14. COLUMN_NAME NUM_ROWS DISTINCT_NUM SELECTIVITY HISTOGRAM NUM_BUCKETS
    15. ------------------------------ ---------- ------------ ----------- --------------------------------------------- -----------
    16. NAME 9999 9999 100 NONE 1
    17. ID 9999 3 .03 FREQUENCY 3

    9、重新收集统计信息


    1. SQL> select * from col_usage$ where obj# = (select object_id from dba_objects where object_name = 'TEST' and owner='SCOTT');
    2. no rows selected
    3. SQL> SQL> exec DBMS_STATS.GATHER_TABLE_STATS(ownname=>'SCOTT',tabname=>'TEST');
    4. PL/SQL procedure successfully completed.
    5. SQL>

    9、再次确认TEST表的统计信息


    发现ID的直方图信息没有了,数据倾斜没有直方图信息,可能导致执行计划不准确。

    1. SQL> set lin 200
    2. SQL> col COLUMN_NAME for a30
    3. SQL> select a.column_name,
    4. 2 b.num_rows,
    5. 3 a.num_distinct distinct_num,
    6. 4 round(a.num_distinct / b.num_rows * 100, 2) selectivity,
    7. 5 a.histogram,
    8. 6 a.num_buckets
    9. 7 from dba_tab_col_statistics a, dba_tables b
    10. 8 where a.owner = b.owner
    11. 9 and a.table_name = b.table_name
    12. 10 and a.owner = 'SCOTT'
    13. 11 and a.table_name = 'TEST';
    14. COLUMN_NAME NUM_ROWS DISTINCT_NUM SELECTIVITY HISTOGRAM NUM_BUCKETS
    15. ------------------------------ ---------- ------------ ----------- --------------------------------------------- -----------
    16. NAME 9999 9999 100 NONE 1
    17. ID 9999 3 .03 NONE 1
    18. SQL>

    ##########

    前面步骤都一样,但是如果导入数据之后,使用repeat的方式收集,直方图信息还在

    1. SQL> set wrap off
    2. SQL> set lin 200
    3. SQL> set lin 200
    4. SQL> col COLUMN_NAME for a30
    5. SQL> select a.column_name,
    6. 2 b.num_rows,
    7. 3 a.num_distinct distinct_num,
    8. 4 round(a.num_distinct / b.num_rows * 100, 2) selectivity,
    9. 5 a.histogram,
    10. 6 a.num_buckets
    11. 7 from dba_tab_col_statistics a, dba_tables b
    12. 8 where a.owner = b.owner
    13. 9 and a.table_name = b.table_name
    14. 10 and a.owner = 'SCOTT'
    15. 11 and a.table_name = 'TEST';
    16. COLUMN_NAME NUM_ROWS DISTINCT_NUM SELECTIVITY HISTOGRAM NUM_BUCKETS
    17. ------------------------------ ---------- ------------ ----------- --------------------------------------------- -----------
    18. NAME 9999 9999 100 NONE 1
    19. ID 9999 3 .03 FREQUENCY 3
    20. SQL> exec DBMS_STATS.GATHER_TABLE_STATS(ownname=>'SCOTT',tabname=>'TEST',ESTIMATE_PERCENT=>10,method_opt=>'for all columns size repeat',cascade=>true,force=>true,degree=>8);
    21. PL/SQL procedure successfully completed.
    22. SQL> set lin 200
    23. SQL> col COLUMN_NAME for a30
    24. SQL> select a.column_name,
    25. 2 b.num_rows,
    26. 3 a.num_distinct distinct_num,
    27. 4 round(a.num_distinct / b.num_rows * 100, 2) selectivity,
    28. 5 a.histogram,
    29. 6 a.num_buckets
    30. 7 from dba_tab_col_statistics a, dba_tables b
    31. 8 where a.owner = b.owner
    32. 9 and a.table_name = b.table_name
    33. 10 and a.owner = 'SCOTT'
    34. 11 and a.table_name = 'TEST';
    35. COLUMN_NAME NUM_ROWS DISTINCT_NUM SELECTIVITY HISTOGRAM NUM_BUCKETS
    36. ------------------------------ ---------- ------------ ----------- --------------------------------------------- -----------
    37. NAME 10009 10009 100 NONE 1
    38. ID 10009 3 .03 FREQUENCY 3
    39. SQL>

    所以,使用expdp/impdp迁移数据库后,如果使用默认的方式收集统计信息,会导致列上面的直方图信息丢失,造成SQL执行计划和原库存在差异,SQL执行效率变低,随着数据库运行一段时间后, col_usage$表中记录的列越来越多,使用默认的方式(for all columns size auto)的方式也会逐渐把列的直方图收集。如果生产中SQL遇到了问题,需要手动收集统计信息(因为SQL已经运行过,where条件中用到的列已经记录到col_usage$中,所以auto的方式也会把where中的列收集直方图)。

  • 相关阅读:
    HTML CSS 网页设计作业「体育小站」(梅西足球 6页 )
    分析ARP解析过程
    前端的页面结构
    【Opencv入门到项目实战】(九):项目实战|信用卡识别|模板匹配|(附代码解读)
    (动态模型类,我的独创)Django的原生ORM框架如何支持MongoDB,同时应对客户使用时随时变动字段
    [SDN]Mininet中的miniedit问题汇总
    基于FPGA的图像直方图统计实现,包括tb测试文件和MATLAB辅助验证
    基于Spring、SpringMVC、Mybatis的超市管理系统
    C语言-结构体
    还在用命令行看日志?快用Kibana吧,可视化日志分析YYDS
  • 原文地址:https://blog.csdn.net/m15217321304/article/details/132852761