Oracle 数据库表性能优化

这篇具有很好参考价值的文章主要介绍了Oracle 数据库表性能优化。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Oracle 数据库表性能优化

最近在一次工作过程中,遇到了oralce 表性能慢的问题。一个历史表,一个月将近1000多万的数据量,想查询这个表的数据,只使用了一个简单的语句,却一个多小时都查不出来。于是决定对Oracle 的这张表的性能进行一下优化。本人不是一个专门搞数据库这块的dba,所以只能粗浅的以自己了解到的知识,以及网上搜的一些资料,来对其进行优化尝试。

下面,我将从以下几点出发,逐一对这个表进行问题排查和优化,并分享一些优化思路:

  1. 数据库索引

  2. 表分区

  3. 统计信息

  4. 表收缩

  5. 并行查询

  6. 表重建

一. 数据库索引

想必一提到表性能优化,数据库索引必然是我们程序员所关注的重点。索引的建立是跟业务息息相关的,我们需要了解到这个表现有的程序怎么用,以及以后的程序要怎么用,从而规划出适合这个表的最合适的索引。而根据阿里java规范,一个表的索引最好不要超过6个,因为建立索引后,表的插入,修改,删除性能都会大大受到影响。因为每次对表进行 DML 操作时,都需要同时对索引进行维护。而如果索引的数量太多或者太大,就会对表操作的性能产生负面影响。
建立索引后,如何正确的使用索引也是需要特别注意的,我们需要尽量去保证SQL语句的简洁性,书写完SQL语句后,需要在执行计划中对语句进行分析测试,去确保这个语句是可以正确使用到我们所建立的索引的。下面我将列出一些关于索引的正确使用,和不正确使用的例子。

  • 索引生效场景:

    1. INDEX_COLUMN = ?

    2. INDEX_COLUMN > ?

    3. INDEX_COLUMN >= ?

    4. INDEX_COLUMN < ?

    5. INDEX_COLUMN <= ?

    6. INDEX_COLUMN between ? and ?

    7. INDEX_COLUMN in (?,?)

    8. INDEX_COLUMN like ?||‘%’

    9. T1.INDEX_COLUMN=T2. COLUMN1(两个表通过索引字段关联)

  • 索引失效场景:

    1. INDEX_COLUMN <> ?

    2. INDEX_COLUMN not in (?,?)

    3. funcation (INDEX_COLUMN) = ? (函数运算后的字段)

    4. INDEX_COLUMN + 1 = ?

    5. INDEX_COLUMN || ‘a’ = ?

    6. INDEX_COLUMN like ‘%’||?

    7. INDEX_COLUMN like ‘%’ || ? || ‘%’ (含前导模糊查询的like 语法不能使用索引)

    8. INDEX_COLUMN is null (B-TREE 索引里不保存字段为 NULL 值记录,因此 is null 不能使用索引)

    9. NUMBER_INDEX_COLUMN = ‘12345’ ; CHAR_INDEX_COLUMN = 12345 (Oracle 在做数值比较时需要将两边的数据转换成同一种数据类型,如果两边数据类型不同时会对字段进行隐式转换,相当于加了一层函数处理)

    10. a.INDEX_COLUMN = a.COLUMN_1 (给索引查询的值应是已知字段,不能是未知字段)

在这里我想举一个我之前未正确使用索引的例子: 在面对 CREATE_TIME 这样的时间字段的时候,ORACLE 中我总是喜欢使用 to_char(CREATE_TIME,‘yyyyMMdd’) 去格式化这个字段,然后查询指定日期。而这样的查询方式,其实会导致CREATE_TIME 这个字段被 to_char() 函数包着,那这个语句也是无法使用索引的,从而导致查询变慢。而正确的时间字段查询方式应该是使用between and ,或者是使用 CREATE_TIME >= date ‘2023-04-15’ 这样的方式去查询时间段,从而保证CREATE_TIME 时间字段索引的有效性。
最后,再分享一下创建索引和重写索引的语句

  1. 建立索引语句
    CREATE INDEX index_name ON table_name (column1, column2);
  2. 重新建立索引语句
    alter index XXX rebuild

分享这两个简单语句的目的,其实还有个小故事。如今的数据库操作软件是有很多的,比如plsql,navicat,dataGrip等等,每款软件都可以以视图化的方式去创建表或者索引,以及执行更多的操作。但是,之前工作的时候,我就尝试使用plsql 的创建索引的方式,去给某个大表加索引,结果,plsql 就卡死了,重启后又执行了多次都没反应。。。后来,我在我马上认为这个大表可能已经建不了索引的时候,我就尝试了下使用索引语句去建立索引,结果就建成功了。所以自打那次后,我就认为最基本的语句操作要比视图化的页面操作靠谱多了,也更高效,更快速,这也就是为什么程序员更喜欢用doc 命令去操作电脑的原因哦!

表分区

oracle 的表分区有两个策略,分别是 RANGE 和 LIST

  • 创建range分区表
CREATE TABLE sales
(
  dept_no     number,
  part_no     varchar2,
  country     varchar2(20),
  date        date,
  amount      number
)
PARTITION BY RANGE(date)
(
  PARTITION q1_2012 
    VALUES LESS THAN('2012-Apr-01'),
  PARTITION q2_2012 
    VALUES LESS THAN('2012-Jul-01'),
  PARTITION q3_2012 
    VALUES LESS THAN('2012-Oct-01'),
  PARTITION q4_2012 
    VALUES LESS THAN('2013-Jan-01')
);
  • 添加range 分区
    ALTER TABLE sales ADD PARTITION q1_2013 VALUES LESS THAN('01-APR-2013');

  • 创建 LIST 分区表

CREATE TABLE sales
(
  dept_no     number,   
  part_no     varchar2,
  country     varchar2(20),
  date        date,
  amount      number
)
PARTITION BY LIST(country)
(
  PARTITION europe VALUES('FRANCE', 'ITALY'),
  PARTITION asia VALUES('INDIA', 'PAKISTAN'),
  PARTITION americas VALUES('US', 'CANADA')
);
  • 添加 LIST 分区

ALTER TABLE sales ADD PARTITION east_asia VALUES ('CHINA', 'KOREA');

创建完分区表后,我们就可以针对分区进行一些操作:

  • 删除分区 ALTER TABLE SALES DROP PARTITION P3;
  • 删除子分区 ALTER TABLE SALES DROP SUBPARTITION P4SUB1;
  • 截断分区 ALTER TABLE SALES TRUNCATE PARTITION P2;
  • 合并分区
    合并分区是将相邻的分区合并成一个分区,结果分区将采用较高分区的界限,值得注意的是,不能将分区合并到界限较低的分区。以下命令实现了P1 P2分区的合并
    ALTER TABLE SALES MERGE PARTITIONS P1,P2 INTO PARTITION P2;
  • 拆分分区
    拆分分区将一个分区拆分两个新分区,拆分后原来分区不再存在。注意不能对HASH类型的分区进行拆分
    ALTER TABLE SALES SBLIT PARTITION P2 AT(TO_DATE('2003-02-01','YYYY-MM-DD')) INTO (PARTITION P21,PARTITION P22);
  • 接合分区
    结合分区是将散列分区中的数据接合到其它分区中,当散列分区中的数据比较大时,可以增加散列分区,然后进行接合,值得注意的是,接合分区只能用于散列分区中。通过以下命令进行接合分区
    ALTER TABLE SALES COALESCA PARTITION;
  • 重命名表分区 ALTER TABLE SALES RENAME PARTITION P21 TO P2;

如何正确使用分区

  1. 使用 PARTITION 关键字 SELECT * FROM SALES PARTITION(europe)
  2. 查询条件带分区键 SELECT * FROM SALES where country = ''

一般情况下我都会使用查询条件带分区键的方式使用分区表,以减少要查的数据不在某个分区表中,而造成了数据丢失的情况。

表统计信息

对于大表,需要及时统计表的信息,让优化器更准确地选择查询执行计划,提高查询速度。具体而言,它会计算并更新该表中的各列的统计信息(如列的最小值、最大值、平均值等),以便优化查询操作。这些命令通常可以提高数据库的性能,因为当查询语句需要访问某些列时,数据库不必在查询时重新计算它们的统计信息,从而可以提高查询的速度。下面是关于处理表统计信息的语句:

  1. 表统计 :ANALYZE TABLE table_name COMPUTE STATISTICS
  2. 索引统计: ANALYZE INDEX index_name COMPUTE STATISTICS;
  3. 表统计 + 索引统计 + 列统计:ANALYZE TABLE table_name COMPUTE STATISTICS for table for all indexes for all columns;
  4. 查询统计信息:select NUM_ROWS,BLOCKS,AVG_SPACE,AVG_ROW_LEN from user_tables where table_name= ' table_name' ;
  5. 根据统计信息进行数据库空间水位分析
SELECT table_name,
       ROUND((blocks * 8/1024), 2) "高水位空间 M",
       ROUND((num_rows * avg_row_len / 1024/1024), 2) "真实使用空间 M",
       ROUND((blocks * 10 / 100) * 8, 2) "预留空间(pctfree) M",
       ROUND((blocks * 8 - (num_rows * avg_row_len / 1024) -blocks * 8 * 10 / 100), 2) "浪费空间 M",
       ((blocks * 8-(num_rows * avg_row_len / 1024))/1024)/(blocks * 8/1024) "浪费空间 %"
  FROM user_tables
 WHERE table_name = 'table_name'

一般情况下,浪费空间大于百分之25%,则需要重新对表磁盘空间进行整理,我这里推荐一种方法,使用 Oracle 10g提供的一个功能: 表收缩操作。

表收缩

从10g开始,oracle开始提供 Shrink 的命令,假如我们的表空间中支持自动段空间管理 (ASSM) ,就可以使用这个特性缩小段,即降低HWM。这里需要强调一点,10g的这个新特性,仅对ASSM表空间有效,否则会报 ORA-10635: Invalid segment or tablespace type。 的错误。

使用 shrink 命令 必须开启行迁移功能,步骤如下:

  • alter table table_name_1 enable row movement ;
    这个语句的作用是启用表的行迁移功能。当表启用了行迁移功能后,可以将表的行从一个表空间移动到另一个表空间,或者重新分配行的存储空间。这可以帮助优化表的存储和性能,同时也可以在需要时对表的结构进行调整。
  • alter table table_name_1 shrink space cascade;
    这条SQL语句的作用是收缩表 table_name_1 的磁盘空间,并且同时级联收缩其所有的索引和分区。收缩磁盘空间的过程会把表中未使用的数据页或数据块空间释放掉,从而最大限度地减小表的物理存储空间,提高数据库的性能和效率。
  • alter table table_name_1 disable row movement ;
    执行完毕后关闭表的行迁移功能。

shrink 命令

使用表收缩的shrink 命令 分为两个阶段:

  1. 数据重组(compact):通过一系列insert、delete操作,将数据尽量排列在段的前面。在这个过程中需要在表上加RX锁,即只在需要移动的行上加锁。由于涉及到rowid的改变,需要enable row movement.同时要disable基于rowid的trigger.这一过程对业务影响比较小。
  2. HWM调整:第二阶段是调整HWM位置,释放空闲数据块。此过程需要在表上加X锁,会造成表上的所有DML语句阻塞。在业务特别繁忙的系统上可能造成比较大的影响。

所以如果我们想整理某个表的磁盘空间,但这个表却在某个业务时间段内经常使用,我们先执行
shrink space compact 这个命令 ,先执行shrink 命令的第一步 :数据重组步骤,然后在业务不繁忙的时候,再去执行 shrink 命令。

并行查询

在某些情况下,我们可以尝试开启Oracle 的并行查询功能,以提高查询速率。但一定要经过执行计划的分析测试,以确保并行查询可以提高语句的查询速度,而不是适得其反。下面是几种使用并行查询的方式:

  1. 使用提示 暗示hints式(临时有效)

SELECT /*+ PARALLEL(a 4),(b 4)*/ a.msisdn_id,b.copyright_id,FROM musicdw.user_list partition(p1) a JOIN musicdw.song_list b ON 1 = 1;

  1. 多表关联时的多表并行场景
    select /*+parallel(table_name1,num1) parallel(table_name2,num2)*/ count(*) from table_name1, table_name2;

  2. 并行DDL式 (会话生命周期有效)

alter session enable parallel dml;
alter session enable parallel query;
或者
ALTER SESSION FORCE PARALLEL DML PARALLEL 5;
ALTER SESSION FORCE PARALLEL QUERY PARALLEL 5;

  1. 修改对象式 (长期有效)

alter table table_name parallel 4; --强制为4个并发也可以更多。
alter table table_name parallel; --让系统自己动态的调整。

表重建

系统修复最简单直接有效的方式就是重启,而表修复最直接有效的方式就是重新建表。在进行表性能优化时,如果尝试了很多方式都没有效果,不如就重新建表吧。重新建一张大表虽然耗费的时间可能很长,也可能这种行为会被人所病垢不明就里,却不失为一个最简单解决问题的方式哈。

今天的分享就到这里,希望能对看完的你有所帮助。后续我会做一个ChatGPT 的项目,使用ChatGPT帮助我更好的整理计划和文档,祝自己好运。文章来源地址https://www.toymoban.com/news/detail-770685.html

参考文献

  1. https://www.php.cn/oracle/489595.html oracle怎么给表增加分区
  2. https://blog.csdn.net/weixin_36303305/article/details/116388233 oracle alter table after,收缩表alter table shrink space

到了这里,关于Oracle 数据库表性能优化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Oracle-数据库性能变慢问题分析

    问题背景:         应用运维报障说最近两天业务数据入库和表查询都变得很慢,需要排查一下数据库的性能问题 问题分析:         登录到服务器上,通过TOP命令快速看了一下,服务器整体的CPU使用%usr不算特别高,但%wa IO等待很高,怀疑有可能是数据库存在大量的

    2024年01月20日
    浏览(56)
  • 【数据库】日常使用PL/SQL 登录ORACLE 数据库查询数据

    一、PL/SQL 登录方式 username: ##访问数据库的账号 password: ##访问数据库的密码 Databse: ##数据库IP地址/实例名 数据库集群心跳地址/实例名 Connect as : ##Normal,如果使用sysdba账户登录选择SYSDBA 二、PL/SQL使用SQL语句查询 点击上方导航栏,New,选择SQL Window,即可再次输入要查询的

    2024年02月19日
    浏览(68)
  • oracle数据库常见的优化步骤与脚本

    要优化 Oracle 数据库的性能,可以按照以下步骤进行: 1. 性能分析和诊断:首先,使用 Oracle 提供的性能分析工具(如 AWR 报告、ASH 报告)对数据库进行分析和诊断。这些报告可以帮助您确定数据库的性能瓶颈和潜在问题。 2. 优化 SQL 查询语句:针对频繁执行的 SQL 查询语句进

    2024年02月09日
    浏览(52)
  • 查询Oracle和MySQL数据库中当前所有连接信息

    查询Oracle当前所有连接信息: 查询MySQL当前所有连接信息: 在这两个查询中,我为每个字段添加了中文别名,以提高查询结果的可读性

    2024年02月12日
    浏览(69)
  • 导出Oracle数据库sqlplus命令行查询的结果到文件

    在Oracle数据库sqlplus命令行操作时,如果想将SQL查询出来的结果导出到文件中,可以使用SQLPlus中的 SPOOL 命令来将查询结果导出到文件。 1.开启日志记录:使用SPOOL命令,指定需要输出的文件路径及文件名。例如: SPOOL /存放路径/oracle.txt 2.执行SQL查询语句:你可以输入任何需要

    2024年02月15日
    浏览(36)
  • Oracle数据库中,授权某用户可以查询其他用户的表

    在Oracle数据库中,授权一个用户可以查看其他所有用户的表,需要执行以下步骤: 使用数据库管理员账号连接到Oracle数据库。 通过 GRANT 命令给用户授予必要的权限。例如,如果要授权用户 user1 可以查看所有其他用户的表,可以执行以下命令: 这条命令将授予 user1  SELECT

    2024年02月08日
    浏览(67)
  • 使用免费负载生成器swingbench对oracle数据库进行压力测试(测试Oracle的功能或评估性能)

    Swingbench 是一个免费负载生成器(和基准测试),旨在对 Oracle 数据库 进行压力测试。目前最新版本 Swingbench 2.6。 SwingBench 由负载生成器,协调器和集群概述组成。该软件可以生成负载 并绘制交易/响应时间图表。 Swingbench 可用于演示和测试技术,例如实际应用程序集群,在线

    2024年02月10日
    浏览(56)
  • oracle查询数据库内全部的表名、列明、注释、数据类型、长度、精度等

    Oracle查询数据库内全部的表名、列明、注释、数据类型、长度、精度 效果图: 字段排序,根据表名对字段进行排序

    2024年02月06日
    浏览(51)
  • java serverlets使用数据源连接oracle数据库,并执行查询操作代码

    package chap03; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.PreparedStatement; import java.sql.Statement; import java.util.*; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.Namin

    2024年02月08日
    浏览(51)
  • 查询服务器tns文件路径,oracle数据库tns配置方法详解

    Oracle中TNS的完整定义:transparence Network Substrate透明网络底层, 监听服务是它重要的一部分,不是全部,不要把TNS当作只是监听器。 上图中的CGDB和STDCG就是对应的TNS,HOST是指向数据库服务器的IP,当然局域网内用计算机名称也是可以的。通过客户端Net Manager创建一个连接到数据

    2024年02月09日
    浏览(62)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包