文章适合熟悉mysql,想学习oracle的选手,基本的语法都相差不大,但还是有区别的
一、oracle高水位线问题
1、什么是高水位线
简单来说,oracle存储数据的时候会分配空间,但是删除数据的时候并不会回收空间。这样的话,表的空间就只会越来越大,查询的时间不会因为数据删除而变少。
举个例子:
假如student表了有1000万条数据,使用 select count(*) from student 查询总记录数的时候需要花费2秒,当student的数据被清除到只剩1条数据的时候,再次使用 select count(*) from student 查询总记录数的时候仍然需要花费2秒
2、oracle为什么要这样做
因为分配空间和回收空间的操作是非常耗时的,这对插入和删除的操作影响是巨大的,因为oracle管理的基本都是百万级别的数据,数据变动非常大,需要定期清理没用的数据,又要插入新的数据,频繁地操作空间会耗费大量时间
如果不回收空间,那么就单纯删除数据后,在数据删除的位置标记上一个 “已删除” 的标记就可以了,如果插入新的数据,就会优先从已删除的位置插入就可以了。
表的数据量一般来说是相对稳定,如果建立了索引,这种机制对查询的影响也不会很大,所以这其实是一种比表好的设计
3、如何解决高水位线问题
如果表的数据量非常小,但是查询的时间非常久,那么就可以考虑高水位线的问题了
解决的办法其实也很简单
(1)重构表
先创建中间表缓存数据,删除原表,再创建新表,置入数据即可,参考的sql如下:
create table student_temp as(
select
*
from
student
);
drop table student;
create table student as(
select
*
from
student_temp
);
drop table student_temp;
需要注意的是,如果有索引,需要重新创建索引
(2)不使用全表查询
建立索引,查询的时候使用到索引,那么就可以基本忽略这个问题
二、oracle虚表dual
oracle不允许不完整的查询,例如,mysql可以直接select 1+1,而oracle必须补全语法,使用 select 1+1 from dual
dual是充当一个补全语法的角色,方便本地测试一些函数或是计算的结果,例如查询系统时间:
select sysdate from dual
三、oracle的fetchSize
1、什么是fetchSize
查询数据的时候,数据需要传输到客户端,那么就需要建立传输通道,而fetchSize就决定了这个通道的大小,fetchSize越大,那么花费的空间就越大,会有数据库内存溢出的风险
2、oracle和mysql的fetchSize的区别
oracle和mysql不同的是,mysql默认是没有fetchSize的,所有数据一次性取出,而oracle默认的fetchSize大小是10,每次只能获取10条数据
对于取出数量级100000的数据,如果oracle不调整fetchSize,那么可能需要花费10秒钟,但是系统会相对稳定,就例如说同时访问的请求过多,用户查询的时间会有延迟,但是系统不会奔溃,而fetchSize过大的话,申请的空间比较多,数据库就会有内存溢出的风险
如果发现sql查询得很快,但是在mybatis中需要很久,那可能就是fetchSize的问题了
网上大多都说fetchSize默认调到40-100区间比较合适,这需要根据业务去考虑商榷吧
四、oracle基本语法备忘录
函数/符号 | 作用 | 示例 | 结果 |
---|---|---|---|
concat() | 拼接字符串,在oracle中最多两个参数 | select concat('ab','cd') from dual | abcd |
|| | 拼接字符串,和concat效果是一样的,可以连续拼接 | select 'ab' || 'cd' || 'efg' from dual | abcdefg |
is null | 判断是否为空,不可以用=null来代替 | select * from dual where DUMMY is null | null |
is not null | 判断是否为不为空,不可以用<>null或!=null来代替 | select * from dual where DUMMY is not null | X |
initcap() | 首字母大写,其它字母小写 | select initcap('abcDeF') from dual | Abcdef |
lower() | 所有字母小写 | select lower('abCdEF') from dual | abcdef |
upper() | 所有字母大写 | select upper('abCdEF') from dual | ABCDEF |
trim() | 去掉首位空格 | select trim(' abcd ') from dual | abcd |
substr() | 截取字符串 | select substr('abcdefg',3,2) from dual | cd |
replace() | 替换字符串 | select replace('abcdefg','ab','gg') from dual | ggcdefg |
abs() | 求绝对值 | select abs(-2) from dual | 2 |
ceil() | 向上取整 | select ceil(2.7) from dual | 3 |
floor() | 向下取整 | select floor(2.7) from dual | 2 |
round() | 四舍五入 | select round(2.7) from dual | 3 |
sysdate | 获取当前完整时间 | select sysdate from dual | 2023/8/23 15:07:09 |
to_char() | 将时间按指定格式转换 | select to_char(sysdate,'yyyyMMdd') from dual | 20230823 |
to_char() | 数字转字符串,字符串会靠左显示 | select to_char(1024) from dual | 1024 |
to_number() | 字符串转数字,数字会靠右显示 | select to_number(1024) from dual | 1024 |
to_date() | 按指定格式将数字转换成日期 | select to_date('20230823','yyyy/MM/dd') from dual | 2023/8/23 |