是这样的,例如我有一个B.JSP页面这个页面上有15个下拉框(姑且不讨论这样做是否合理).每个下拉框都对应不同的表去查找数据,那么当我从A.JSP页面转向到ACTION之后 在ACTION的方法体当中通过后台的方法去对每张表进行查询,查询每张表都会调用不同的方法,然后在ACTION里面把每个集合丢到request中返回到B.jsp页面 可是这样一来相当于打开了十几个数据库连接,这样页面在打开的时候相当的慢,我能想到得办法就是写一个方法 只打开一个数据库连接 然后在这个方法中写十几个查询数据库的语句对应不同的表,然后查出来的所有集合都丢到一个集合当中,返回到ACTION在循环取出每个集合。可是这样并非是个好办法。视图也想过,但是每个下拉框的数据都要指定一个标识才能查询到对应的集合,这样一来也不太好。现在想问问大家 各位遇到这种情况一般是怎么处理的?
尝试优化sql
不知道你的具体问题是什么
你好,可能是我叙述的太罗嗦了。其实就是 我要去一次性查询15张表中的数据,每张表查询的方法都打开了一个数据库的连接,只用JAVA代码实现。看是否有什么好一些的优化措施。让速度变得更快一些。
我知道,可以把这些都放在一个方法里面,那么只需要打开一次连接就可以 可是这样的方法 查询还是必不可少的也不是什么好办法。并且即使将这些集合拿到了 在ACTION还要在把每个集合循环出来,效率不见得能高多少。
1、减少数据库连接
2、减少网络传输具体情况具体分析,这15个下拉框的数据能否做个分类,放在一张表里面,比如分为id, 类别,名称,备注,一个类别对应一个下拉框。从A页面经过Action的时候,一次性把这些数据取到,形成一个JSON字符串,到B页面的时候通过脚本做解析,跟每个下拉框对应起来。(也不用形成JSON字符串,也可以在后台做分解再通过B页面获取,不过这样效果就差一点了)
如果这些数据不能放在同一个表,可通过视图,构造要返回的字段,达到同一张表的目的。
这样做,连接一次数据库,一次请求,一次响应。
对于我昨天的回帖。抱歉了。。
晚上看了下oracle的性能优化大全发现LZ这种情况可以做优化。。如下案例:第三种方式正好适合LZ。。
7. 减少访问数据库的次数
当执行每条SQL语句时, ORACLE在内部执行了许多工作: 解析SQL语句, 估算索引的利用率, 绑定变量 , 读数据块等等. 由此可见, 减少访问数据库的次数 , 就能实际上减少ORACLE的工作量.
例如,
以下有三种方法可以检索出雇员号等于0342或0291的职员.
方法1 (最低效)
SELECT EMP_NAME , SALARY , GRADE
FROM EMP
WHERE EMP_NO = 342;
SELECT EMP_NAME , SALARY , GRADE
FROM EMP
WHERE EMP_NO = 291;
方法2 (次低效)
DECLARE
CURSOR C1 (E_NO NUMBER) IS
SELECT EMP_NAME,SALARY,GRADE
FROM EMP
WHERE EMP_NO = E_NO;
BEGIN
OPEN C1(342);
FETCH C1 INTO …,..,.. ;
OPEN C1(291);
FETCH C1 INTO …,..,.. ;
CLOSE C1;
END;
方法3 (高效)
SELECT A.EMP_NAME , A.SALARY , A.GRADE,
B.EMP_NAME , B.SALARY , B.GRADE
FROM EMP A,EMP B
WHERE A.EMP_NO = 342
AND B.EMP_NO = 291;
注意:
在SQL*Plus , SQL*Forms和Pro*C中重新设置ARRAYSIZE参数, 可以增加每次数据库访问的检索数据量 ,建议值为200.
其实还是放在一个sql里去完成所有的查询,我想着是用union all去连接结果集,这样只需要1次连接,1ge 游标,1次解析,1次执行。
如果实时不高而且每次查询谓词都相同的话可以考虑使用物化视图
11g的话如果表更新不频繁的话对每个表的查询提示使用结果缓存select /*+ result_cache*/ ...
如果查询性能还是有问题,就可以看下自己的sql有没有问题,自己可以简单的优化一下,如强选择性字段上建索引
还有问题就交给你的DBA处理吧
方法3 (高效)
SELECT A.EMP_NAME , A.SALARY , A.GRADE,
B.EMP_NAME , B.SALARY , B.GRADE
FROM EMP A,EMP B
WHERE A.EMP_NO = 342
AND B.EMP_NO = 291;这种方式,你难道说不是一次连接?能不用union all为什么硬要去用。。用union all又有额外的性能牺牲。。
你这个其实是一个交叉连接,或者说是一个笛卡尔积连接
举个例子你看下SELECT A.ENAME , A.SAL ,
B.ENAME , B.SAL
FROM EMP A,EMP B
WHERE A.EMPNO = 7499
AND B.EMPNO = 7369;执行计划是
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------------------
| 1 | NESTED LOOPS | | 1 | 1 | 1 |00:00:00.01 | 4 |
| 2 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 1 | 1 |00:00:00.01 | 2 |
|* 3 | INDEX UNIQUE SCAN | EMP_PK | 1 | 1 | 1 |00:00:00.01 | 1 |
| 4 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 1 | 1 |00:00:00.01 | 2 |
|* 5 | INDEX UNIQUE SCAN | EMP_PK | 1 | 1 | 1 |00:00:00.01 | 1 |
-------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------- 3 - access("B"."EMPNO"=7499)
5 - access("A"."EMPNO"=7369)你可以看到操作2和4进行了一个相关联合型操作(NESTED LOOPS 嵌套循环操作),虽然两者都只返回一条记录SELECT A.ENAME , A.SAL ,
B.ENAME , B.SAL
FROM EMP A,EMP B
WHERE A.EMPNO > 7900
AND B.EMPNO > 7902;执行计划
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
--------------------------------------------------------------------------------------------------
| 1 | MERGE JOIN CARTESIAN | | 1 | 1 | 2 |00:00:00.01 | 6 |
| 2 | TABLE ACCESS BY INDEX ROWID | EMP | 1 | 1 | 2 |00:00:00.01 | 4 |
|* 3 | INDEX RANGE SCAN | EMP_PK | 1 | 1 | 2 |00:00:00.01 | 2 |
| 4 | BUFFER SORT | | 2 | 1 | 2 |00:00:00.01 | 2 |
| 5 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 1 | 1 |00:00:00.01 | 2 |
|* 6 | INDEX RANGE SCAN | EMP_PK | 1 | 1 | 1 |00:00:00.01 | 1 |
--------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------- 3 - access("A"."EMPNO">7900)
6 - access("B"."EMPNO">7902)
这个就比较典型了,2和5执行了一个非相关联合操作的笛卡尔积合并连接,但是出现了一次排序而union all是一个典型的非相关联合操作SELECT ENAME , SAL
FROM EMP WHERE EMPNO > 7900
UNION ALL
SELECT ENAME , SAL
FROM EMP WHERE EMPNO > 7902执行计划-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------------------
| 1 | UNION-ALL | | 1 | | 3 |00:00:00.01 | 6 |
| 2 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 1 | 2 |00:00:00.01 | 4 |
|* 3 | INDEX RANGE SCAN | EMP_PK | 1 | 1 | 2 |00:00:00.01 | 2 |
| 4 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 1 | 1 |00:00:00.01 | 2 |
|* 5 | INDEX RANGE SCAN | EMP_PK | 1 | 1 | 1 |00:00:00.01 | 1 |
-------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------- 3 - access("EMPNO">7900)
5 - access("EMPNO">7902)
无论如何,最佳的方法是只打开一次数据库连接,这个并不难做到,除非你数据库操作DAO和数据库操作那些基础类设计的实在太烂。和你具体查询什么,传入查询条件都无关!你这个根本不是什么问题
要查15个表,又是异步,所以执行15个查询也是必须的。数据库执行这点规模的计算实在不算什么,除非都是查的海量数据,条件和索引又都没优化。
剩下的就是包装数据和传输到客户。客户端解析数据。
你可以试试单独执行sql的时间,和前台点击后得到数据的时间。相差无几就从sql语句下手。
如果sql执行的飞快,但是前台展现数据的时间长,就要优化数据封装和解析的方式。