一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情。
1问题处理 1.1问题:表记录不多,占用空间很大,造成SQL执行效率很低 现象:10.16.111.92服务器aptscd库的表bsvcbuslastpositiondatald5记录大概9千多条,各字段均为基础数据,不包括blob等类型,SQL执行效率很低;同时其他产品连接此服务器Oracle系统,查询数据变慢,包括SQL Developer查询也是如此。
原因:可能是该表不断的插入记录, HWM上移,使用delete删除记录,其分配空间不会缩小,HWM(High Water Mark)不会降低。Oracle在执行全表扫描(查询)时,始终是从段一直扫描到HWM,即使没有数据,也会如此,当HWM较高时,就会造成耗时较长。
处理:释放表所占空间(HWM下的自由空间),降低HWM。此表数据量不大,打算使用truncate处理,处理前先备份数据。
注:表中的数据可以更新的,尽量采用update,而不使用先delete、再insert的方式,这可以作为系统优化的一个关注点
以下是本次问题处理过程,及中间过程遇到的其他问题的处理
执行SQL:
select t.* from bsvcbuslastpositiondatald5 t ;
select count(1) from bsvcbuslastpositiondatald5 t;
效率较低,秒级;
执行SQL:
select count(1),t.routeid from bsvcbuslastpositiondatald5 t group by t.routeid;
用时12分钟多。
数据量较少,而且没有存储附件等内容,全是基础数据,以上语句只是分组统计,性能严重低下,检查表占用空间大小:
select t.segment_name, t.segment_type, sum(t.bytes / 1024 / 1024) "占用空间(M)"
from dba_segments t
where t.segment_type='TABLE'
and t.owner = 'APTSCD'
and t.segment_name='BSVCBUSLASTPOSITIONDATALD5'
group by OWNER, t.segment_name, t.segment_type;
注:有些表是有分区的表(segment_type:TABLE、TABLE_PARTITION),可以先不带segment_type,查看其segment_type,然后再将参数带入查看占用空间
引起此问题的原因可能是,该表曾经存储了大量数据,平时可能经常插入、删除,新增记录时,HWM会上移,但使用delete删除记录,其分配空间不会缩小,HWM(High Water Mark)不会降低。Oracle在执行全表扫描(查询)时,始终是从段一直扫描到HWM,即使没有数据,也会如此,当HWM较高时,就会造成耗时较长。
处理:释放表所占空间(HWM下的自由空间),降低HWM。此表数据量不大,打算使用truncate处理,处理前先备份数据。
清空表:
truncate table bsvcbuslastpositiondatald5;
恢复数据,再看表占用空间,约2M
再次执行效率较低的SQL语句:
select count(1),t.routeid from bsvcbuslastpositiondatald5_1 t group by t.routeid;
用时0.078秒
补充说明:处理这种问题,可能一般不使用truncate,使用move(alter table table_name move,索引会失效,需要重建索引),或者使用shrink space(alter table table_name shrink space)。推荐使用move
1.2TNS-12520: TNS: 监听程序无法为请求的服务器类型找到可用的处理程序 Sqlplus连接,报错ORA-00020:maximum number of processes (300) exceeded
Oracle的process数默认较小,可根据需求,适当调整process值,同时调整session值。
停止Oracle连接,sysdba登录,查看最大连接数: select value from v$parameter where name = 'processes';
或者show parameter processes;
查看process数:select count(*) from v$processes
更改进程数 alter system set processes=500 scope=spfile
修改session数,对应关系sessions=processes*1.5+5
alter system set sessions=755 scope=spfile;
关闭数据库 shutdown immediate
启动数据库使配置生效 startup;
1.3ORA-01940: 无法删除当前已连接的用户
SQL> drop user a cascade;
drop user a cascade
ERROR 位于第 1 行:
ORA-01940: 无法删除当前已连接的用户
解决方法:
SQL> select username,sid,serial# from v$session;
USERNAME SID SERIAL#
1 1
2 1
3 1
4 1
5 1
6 1
7 1
SYS 8 3
A 9 4
已选择9行。
SQL> alter system kill session'9,4';
系统已更改。
SQL> drop user a cascade;
用户已丢弃
1.4调整Oracle内存大小 查看Memory参数:
Sys用户登录:
show parameter sga;
show parameter memory;
sga_max_size、sga__size、memory_max_target、memory_target都是50G;
注意:如果确实有需要调整,要谨慎,万一挂了,就都放假了
alter system set sga_max_size=25920M scope=pfile;
alter system set memory_max_target=25920M scope=pfile;
重启服务,或者:
shutdown immediate;
startup;
注意:memory_max_target要大于等于sga_max_size,否则数据库启动失败,使用sqlplus连接时,提示无法识别,报:ORA-12514 TNS:监听程序当前无法识别连接描述符中请求的服务;
检查报警日志:D:\app\Administrator\diag\rdbms\apts\apts\trace下的alert_apts.log,cmd下执行命令:
cmd:sqlplus / as sysdba
执行startup,报错:
ORA-00837: Specified value of MEMORY_TARGET greater than MEMORY_MAX_TARGET
引起的原因:以前设置了MEMORY_TARGET值为50G,本次调整MEMORY_MAX_TARGET之后,造成MEMORY_TARGET大于MEMORY_MAX_TARGET,数据库无法启动。(MEMORY_TARGET要小于等于MEMORY_MAX_TARGET)
打开D:\app\Administrator\product\11.2.0\dbhome_1\database\SPFILEAPTS.ORA,里边的:
*.memory_target=53687091200
还是以前设置的50G,但不能直接编辑此文件,修改后该配置文件会无效;
修复方法:
sqlplus / as sysdba
create pfile from spfile;
文件在D:\app\Administrator\product\11.2.0\dbhome_1\database\INITapts.ORA
因为根据spfile创建的pfile,所以参数值未变,需要修改pfile,可直接编辑:
从D:\app\Administrator\admin\apts\pfile\init.ora.109201716387,找到memory_target=27138195456
打开D:\app\Administrator\product\11.2.0\dbhome_1\database\INITapts.ORA,将*.memory_target=27138195456,保存,执行
startup pfile= 'D:\app\Administrator\product\11.2.0\dbhome_1\database\INITapts.ORA';
可以启动,但不能使用alter system修改参数,再创建spfile
create spfile from pfile;
重启Oracle服务,成功;
1.5sqlplus连接oracle乱码 要解决Oracle的客户端乱码问题关键是要把服务器端使用的字符集跟客户端使用的字符集统一起来。Oracle客户端(Sqlplus)通过NLS_LANG环境变量来确定客户端使用的字符集。NLS_LANG参数由以下部分组成: NLS_LANG=_.
NLS_LANG各部分含义如下: LANGUAGE指定: -Oracle消息使用的语言 -日期中月份和日显示 TERRITORY指定 -货币和数字格式 -地区和计算星期及日期的习惯 CHARACTERSET: -控制客户端应用程序使用的字符集 通常设置或者等于客户端(如Windows)代码页 oracle字符集问题一般可以分为三类: 数据库字符集, sqlplus的字符集(客户端字符集), 终端程序的字符集(非oracle的)。 v$nls_parameters,表示会话自己的设置,可能是会话的环境变量或者是alter session完成,如果会话没有特殊的设置,将与nls_instance_parameters一致。 客户端的字符集要求与服务器一致,才能正确显示数据库的非Ascii字符。如果多个设置存在的时候,alter session>环境变量>注册表>参数文件 字符集要求一致,但是语言设置却可以不同,语言设置建议用英文。如字符集是zhs16gbk,则nls_lang可以是zhs16gbk。 unix下类似, 不过nls_lang要大写NLS_LANG, 在.profile或这.bash_profile(根据你用的shell)里更改NLS_LANG可以长久保持环境变量值
1.6没有匹配的验证协议 ORA-28040:没有匹配的验证协议
解决方法:在/home/oracle/app/oracle/product/19.3.0/db_1/network/admin中增加SQLNET.ALLOWED_LOGON_VERSION=8
1.7解决sqlplus无法使用退格键删除前一个字符等 在linux下面使用sqlpus连接数据库处理,实在不是很方便,通过工具rlwrap能够调用历史命令和回调功能,提高效率。
1、安装前准备
[root@centos7]# yum install -y gcc
[root@centos7]# yum install -y libtermcap-devel
[root@centos7]# yum install -y readline
[root@centos7]# yum install -y readline-devel
2、安装rlwrap
[root@centos7]# tar -zxvf rlwrap-0.30.tar.gz [root@centos7]# cd rlwrap-0.30 [root@centos7 rlwrap-0.30]# ./configure ---配置 [root@centos7 rlwrap-0.30]# make ---编译 [root@centos7 rlwrap-0.30]# make install –安装
(1)./configure是用来检测你的安装平台的目标特征的。比如它会检测你是不是有CC或GCC,并不是需要CC或GCC,它是个shell脚本。
(2)make是用来编译的,它从makefile中读取指令,然后编译。
(3)make install是用来安装的,它也从makefile中读取指令,安装到指定的位置。
3、配置rlwrap
[root@centos7 rlwrap-0.30]# vi /home/oracle/.bash_profile 添加 alias sqlplus='rlwrap sqlplus' alias rman='rlwrap rman'
[root@centos7]# source /home/oracle/.bashrc
4、安装遇到的问题
(1)[root@centos7 rlwrap-0.37]# make
make: *** 没有指明目标并且找不到 makefile。 停止。
解决方案:查看是否缺少依赖包
1.8手动启停数据库时报错:ORA-01034: ORACLE not available ,ORA-27101: shared memory realm does not exist 解决办法:
这里并不是内存不够的问题,而是数据库没有找到你需要连接的实例SID。两种情况:
一是你的数据库ORACLE_HOME或ORACLE_SID设置错误;
二是Oracle没有找到你所需要的实例。
对于已经运行了一段时间的Oracle,大多情况是第二种情况,解决方法也很简单,就是手动修正,让系统知道你要启动的是哪个实例:
在Linux系统中,可以使用命令查看当前实例
[oracle@ORACLE247 ~]ORACLE_SID
[oracle@ORACLE247 ~]$ export ORACLE_SID=orcl(修改成你要启动的数据库实例)
然后再执行启动命令:
[oracle@ORACLE247 ~]$ sqlplus / as sysdba
SQL> startup
2知识点 2.1建立索引的技巧 一、合理选取字段:
1、读取表的时候必须考虑的,筛选一定会用到的字段。
2、识别率(差异率)高的字段。
二、合理索引顺序
1、group by,order by必须与索引顺序一致,聚合、排序的第一个字段必须为索引开始字段,未索引的字段尽量不要做汇聚和排序的字段。
2、按照常用筛选条件的优先级建立组合索引。
三、索引字段不能太多。
四、合理添加分区和索引
充分考虑数据的增长特性,保证数据在可见的时间范围内,效率没有明显波动。
总量千万级别必须建立分区,每个分区数据量不超过百万,百万以上的数据量必须建立索引。
2.2常见的导致查询不使用索引的情况 在Oracle数据库中,客户端提交的SQL语句的执行计划是由后台的优化器根据解
析后的语句和表的相关统计信息生成的,因此在某些情况下会导致执行计划没有
用到表上的索引,常见的原因有如下几种:
表的统计信息收集不正确。 Oracle后台会定期对统计信息进行收集,当统计信息为空时,Oralce优化器也会通过临时采样的方式来分析表的统计信息。但是非空且错误的统计信息会对优化器产生误导导致优化器选择不使用索引。
解决方法:
查看user_tables或user_tab_partitions的num_rows列,将不正确的统计信息使用dbms_stats.delete_table_stats脚本删除掉。
分区表的部分分区索引不可用 因为分区表的索引也是分区的,所以当查询范围内的分区索引不可用时,优化器不会选择使用索引。
解决方法:
查询user_ind_partitions表的status列,将状态为UNUSABLE的索引使用alter index XXX rebuild partition XXX 将对应索引的分区重建。
隐式的类型转换 这种情况多发生在查询条件的列类型和条件类型不一致时导致隐式的类型转换。例如select * from tab where c1=123; 当c1的类型为char型时,后台会自动将语句改写成 select * from tab where to_number(c1)=123; 此时会导致索引不可用。
解决方法:
在查询条件中使用与列相对的数据类型,例如将语句改写成:
select * from tab where c1='123';
查询条件使用了函数或者转换 此处的函数包括任意对字段进行的修改,比如字段为C,那么C*1,-C,C+1,
To_char(C)等等。
当对查询条件使用了函数时,例如如下查询:
select * from tab where substr(c1,1,3)='123';
优化器不会使用普通索引。此时需要建立相应的函数索引【极度不建议】 。
解决方法:
在查询列创建函数索引。
create index idx_tab_substrc1 on tab(substr(c1,1,3));
当like条件以%开头时,优化器无法使用索引 例如当使用where c1 like'%A'时,优化器因为无法找到索引的开始节点所以不会使用索引。
解决方法:
在查询条件中尽量不要使用前模糊查询,如果一定要使用,则需要在对应列上使用反向函数索引。
create index tab_reverse index on tab(reverse(c1));
select * from tab where reverse(c1) like reverse('%A');
索引的差异度不够高 当索引列的差异度不高时(例如性别列)。需要建立位图索引而不是普通的索引。创建位图索引使用如下语句:
create bitmap index idx_bitmap_gender on tab(gender);
当使用<>判断时,优化器无法使用索引 当使用where c1 <> 'abc'时,优化器不会使用索引。
解决方法:
将查询条件改为c1>'abc'or c1<'abc'。
当查询出的数据量占表的数据总量比比较大(大于20%)时,优化器会选择全表快速扫描而非使用索引。
2.3TRUNCATE TABLE 与 DELETE区别 1.DELETE
・DML语言
・可以回退
・可以有条件的删除
DELETE FROM 表名
WHERE 条件
2.TRUNCATE TABLE
・DDL语言
・无法回退
・默认所有的表内容都删除
・删除速度比delete快。
TRUNCATE TABLE 表名
1、TRUNCATE在各种表上无论是大的还是小的都非常快。如果有ROLLBACK命令Delete将被撤销,而TRUNCATE则不会被撤销。
2、TRUNCATE是一个DDL语言,向其他所有的DDL语言一样,他将被隐式提交,不能对TRUNCATE使用ROLLBACK命令。
3、TRUNCATE将重新设置高水平线和所有的索引。在对整个表和索引进行完全浏览时,经过TRUNCATE操作后的表比Delete操作后的表要快得多。
4、TRUNCATE不能触发任何Delete触发器。
5、当表被清空后表和表的索引讲重新设置成初始大小,而delete则不能。
6、不能清空父表。
在oracle里,使用delete删除数据以后,数据库的存储容量不会减少,而且使用delete删除某个表的数据以后,查询这张表的速度和删除之前一样,不会发生变化。
因为oralce有一个HWM高水位,它是oracle的一个表使用空间最高水位线。当插入了数据以后,高水位线就会上涨,但是如果你采用delete语句删除数据的话,数据虽然被删除了,但是高水位线却没有降低,还是你刚才删除数据以前那么高的水位。除非使用truncate删除数据。那么,这条高水位线在日常的增删操作中只会上涨,不会下跌,所以数据库容量也只会上升,不会下降。而使用select语句查询数据时,数据库会扫描高水位线以下的数据块,因为高水位线没有变化,所以扫描的时间不会减少,所以才会出现使用delete删除数据以后,查询的速度还是和delete以前一样。
2.4回收站 Oracle10g以后增加了回收站的功能,其作用类似于windows的回收站
Drop的对象,会放在回收站中
默认情况下,Oracle是将此功能开启的。但是在有些情况下,我们不希望对删除的表进行回收,则可以采用如下方式设置:
1、session级别的 alter session set recyclebin=off;
2、system级别的 alter system set recyclebin=off;
系统管理员登录
select * from sys.recyclebin$ t order by t.droptime desc;
闪回
flashback table phistest.atest to before drop;
闪回时重命名
flashback table phistest.atest to before drop rename to tablename_new;
越过回收站直接删除:
drop table atest purge;
drop user cascade;
drop tablespace users including contents;
清空回收站:
purge index idx_1;
purge user_recyclebin;
purge dba_recyclebin;
2.5Oracle密码 密码过期修改 密码超期,用户状态为“LOCKED(TIMED)”,使用管理员账户登录sqlplus:
看看dba_users中该用户的状态等信息
SQL>select username,account_status,lock_date,profile from dba_users;
解锁:SQL>alter user test account unlock;
修改密码:SQL>alter user test identified by test;
密码期限修改 首先查看用户的profile是使用的哪个,一般是DEFAULT:
select username , PROFILE from dba_users ;
查看密码期限:
select * from dba_profiles where profile='DEFAULT' and resource_name = 'PASSWORD_LIFE_TIME';
修改密码期限为无限期
ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED
2.6在WIN7、Win10上安装oracle 10g 提示 5.0,5.1,5.2,6.0 在Win7、Win10系统安装Oracle10、11g等,提示如下信息:
正在检查操作系统要求...
要求的结果: 5.0,5.1,5.2,6.0 之一
实际结果: 6.1
检查完成。此次检查的总体结果为: 失败 <<<<
问题: Oracle Database 10g 未在当前操作系统中经过认证。
建议案: 确保在正确的平台上安装软件。
解决方法:
找到 refhost.xml 文件(位置:database/stage/prereq/db,打开 refhost.xml 配置文件并找到 <CERTIFIED_SYSTEMS> 节点,接着在节点后面添加,如下信息:
<OPERATING_SYSTEM>
</OPERATING_SYSTEM>
<OPERATING_SYSTEM>
</OPERATING_SYSTEM>
2.7PowerDesigner反向工程导出数据库设计 当项目缺少数据库设计文档时,可通过此方式导出数据库设计报告。
前提:数据表带有注释