目录
一、减少数据访问
创建索引,利用索引直接查找数据,避免扫描全表。
能利用索引的SQL样本:
INDEX_COLUMN = ?
INDEX_COLUMN > ?
INDEX_COLUMN >= ?
INDEX_COLUMN < ?
INDEX_COLUMN <= ?
INDEX_COLUMN between ? and ?
INDEX_COLUMN in (?,?,...,?)
INDEX_COLUMN like ?||'%'(后导模糊查询)
T1. INDEX_COLUMN=T2. COLUMN1(两个表通过索引字段关联)
不能利用索引的SQL样本:
查询条件 | 不能使用索引原因 |
INDEX_COLUMN <> ? INDEX_COLUMN not in (?,?,...,?) |
不等于操作不能使用索引 |
function(INDEX_COLUMN) = ? INDEX_COLUMN + 1 = ? INDEX_COLUMN || 'a' = ? |
经过普通运算或函数运算后的索引字段不能使用索引 |
INDEX_COLUMN like '%'||? INDEX_COLUMN like '%'||?||'%' |
含前导模糊查询的Like语法不能使用索引 |
INDEX_COLUMN is null | B-TREE索引里不保存字段为NULL值记录,因此IS NULL不能使用索引 |
NUMBER_INDEX_COLUMN='12345' CHAR_INDEX_COLUMN=12345 |
Oracle在做数值比较时需要将两边的数据转换成同一种数据类型,如果两边数据类型不同时会对字段值隐式转换,相当于加了一层函数处理,所以不能使用索引。 |
a.INDEX_COLUMN=a.COLUMN_1 | 给索引查询的值应是已知数据,不能是未知字段值。 |
创建索引条件:
1、字段出现在查询条件中,并且查询条件可以使用索引;
2、语句执行频率高,一天会有几千次以上;
3、通过字段条件可筛选的记录集很小,那数据筛选比例是多少才适合?
这个没有固定值,需要根据表数据量来评估,以下是经验公式,可用于快速评估:
小表(记录数小于10000行的表):筛选比例<10%;
大表:(筛选返回记录数)< (表总记录数*单条记录长度)/10000/16
(单条记录长度≈字段平均内容长度之和+字段数*2)
建B-TREE索引的经验分类:
字段类型 | 常见字段名 | |
需要建索引的字段 | 主键 | ID,PK |
外键 | PRODUCT_ID,COMPANY_ID,MEMBER_ID,ORDER_ID,TRADE_ID,PAY_ID | |
有对像或身份标识意义字段 | HASH_CODE,USERNAME,IDCARD_NO,EMAIL,TEL_NO,IM_NO | |
索引慎用字段,需要进行数据分布及使用场景详细评估 | 日期 | GMT_CREATE,GMT_MODIFIED |
年月 | YEAR,MONTH | |
状态标志 | PRODUCT_STATUS,ORDER_STATUS,IS_DELETE,VIP_FLAG | |
类型 | ORDER_TYPE,IMAGE_TYPE,GENDER,CURRENCY_TYPE | |
区域 | COUNTRY,PROVINCE,CITY | |
操作人员 | CREATOR,AUDITOR | |
数值 | LEVEL,AMOUNT,SCORE | |
长字符 | ADDRESS,COMPANY_NAME,SUMMARY,SUBJECT | |
不适合建索引的字段 | 描述备注 | DESCRIPTION,REMARK,MEMO,DETAIL |
大字段 | FILE_CONTENT,EMAIL_CONTENT |
二、返回更少数据
1、客户端(应用程序或浏览器)分页
将数据从应用服务器全部下载到本地应用程序或浏览器,在应用程序或浏览器内部通过本地代码进行分页处理
优点:编码简单,减少客户端与应用服务器网络交互次数
缺点:首次交互时间长,占用客户端内存
适应场景:客户端与应用服务器网络延时较大,但要求后续操作流畅,如手机GPRS,超远程访问(跨国)等等。
2、应用服务器分页
将数据从数据库服务器全部下载到应用服务器,在应用服务器内部再进行数据筛选。以下是一个应用服务器端Java程序分页的示例:
List list=executeQuery(“select * from employee order by id”);
Int count= list.size();
List subList= list.subList(10, 20);
优点:编码简单,只需要一次SQL交互,总数据与分页数据差不多时性能较好。
缺点:总数据量较多时性能较差。
适应场景:数据库系统不支持分页处理,数据量较小并且可控。
3、数据库SQL分页
采用数据库SQL分页需要两次SQL完成
一个SQL计算总数量
一个SQL返回分页后的数据
优点:性能好
缺点:编码复杂,各种数据库语法不同,需要两次SQL交互。
4、只返回需要的字段
通过去除不必要的返回字段可以提高性能。
优点:
a、减少数据在网络上传输开销
b、减少服务器数据处理开销
c、减少客户端内存占用
d、字段变更时提前发现问题,减少程序BUG
e、如果访问的所有字段刚好在一个索引里面,则可以使用纯索引访问提高性能。
5、优化业务逻辑
三、减少交互次数
使用数据库访问框架批量提交的接口
四、减少服务器CPU开销
使用绑定变量
绑定变量是指SQL中对变化的值采用变量参数的形式提交,而不是在SQL中直接拼写对应的值。
非绑定变量写法:Select * from employee where id=1234567
绑定变量写法:
Select * from employee where id=?
Preparestatement.setInt(1,1234567)
Java中Preparestatement就是为处理绑定变量提供的对像,绑定变量有以下优点:
1、防止SQL注入
2、提高SQL可读性
3、提高SQL解析性能,不使用绑定变更我们一般称为硬解析,使用绑定变量我们称为软解析。
使用绑定变量提高SQL解析性能原因:
当一条SQL发送给数据库服务器后,系统首先会将SQL字符串进行hash运算,得到hash值后再从服务器内存里的SQL缓存区中进行检索,如果有相同的SQL字符,并且确认是同一逻辑的SQL语句,则从共享池缓存中取出SQL对应的执行计划,根据执行计划读取数据并返回结果给客户端。
如果在共享池中未发现相同的SQL则根据SQL逻辑生成一条新的执行计划并保存在SQL缓存区中,然后根据执行计划读取数据并返回结果给客户端。
为了更快的检索SQL是否在缓存区中,首先进行的是SQL字符串hash值对比,如果未找到则认为没有缓存,如果存在再进行下一步的准确对比,所以要命中SQL缓存区应保证SQL字符是完全一致,中间有大小写或空格都会认为是不同的SQL。
如果我们不采用绑定变量,采用字符串拼接的模式生成SQL,那么每条SQL都会产生执行计划,这样会导致共享池耗尽,缓存命中率也很低。
五、利用更多资源
1、客户端多进程并行访问
2、数据库并行处理