oracleテンポラリテーブルの運用研究
質問:次のSQL文を参照してください.
中にはN個以上のorがクエリ時の性能に影響しているので、この問題を解決する方法を考えます
問題の解決策:
テンポラリ・テーブルを使用して、これらのorの条件をテンポラリ・テーブルに挿入してから、コンビネーション・クエリーの方法で解決します.コンビネーション・クエリーは、これだけのorを使用するよりも速いです.
ソリューションの実行可能性分析:
仮表の特性によって、理論的には可能ですが、これらのものを変えるのは私たちのforcoreの枠組みの下に制限されているので、変えるのはそんなに簡単ではありません.次に、私のこの解決過程を書いて、もっと良い解決方法があるかどうかを検討します.
まず、Oracleテンポラリ・テーブルについて詳しく説明します.
Oracleテンポラリ・テーブルを作成します.2つのタイプのテンポラリ・テーブルがあります.
1.セッション・レベルのテンポラリ・テーブル
2.取引レベルのテンポラリ・テーブル
2つのタイプのテンポラリ・テーブルの違い:
セッションレベルのテンポラリ・テーブルはon commit preserve rowsを採用する.トランザクションレベルはon commit delete rowsを採用しています.使用法では、セッションレベルは、セッションが終了したテンポラリ・テーブルのデータのみが切断され、トランザクション・レベルのテンポラリ・テーブルはcommit、rollback、またはセッションが終了した場合にのみ、テンポラリ・テーブルのデータが切断されます.接続プールを使用しない場合は、jdbc接続を2つのタイプのテンポラリ・テーブルで実験します.接続プールに接続が1つしかない場合でも、目的の結果が得られます.この部分に関する試験コードは以下の通りである:表admin_work_areaはセッションレベルのテンポラリ・テーブルで、ここの接続プールは1つの接続のみを構成します.
問題の解決を開始:上記のような直接データベースに接続する試験コードを使って、私たちが想像していたように、この問題が解決しやすいと感じて、forcoreの中で直接修正しました.forcoreの中に接続プールが配置されているので、問題が発生しました.私たちが挿入したデータが見えます.私たちが挿入したデータが見えません.これは、使用する接続プールの接続が異なるためであり、接続プールの接続は破棄されません.繰り返しの試験とネット上で関連資料を探しても、使用時に1つの接続しか使用できないことを保証することはできません.毎回、接続プールに異なる接続を取ってもらうことはできません.デルのforcoreでは、DAO実装クラスの一般的なコードは次のとおりです.
私たちが始めたとき、それを次のようにして臨時表を運用しました.
多くの部分は私たちがテンポラリ・テーブルにデータを挿入するために使用しています.次の文はテンポラリ・テーブルと組み合わせてクエリーするために使用されています.私たちのテンポラリ・テーブルはセッション・レベルで使用されています.私たちの考えでは、このように使用すればいいのですが、私たちが挿入したデータは、私たちが下で取るときには全然見えません.getSqlMapClientTemplate()を1つ使うたびに、彼は別の接続を取ります.その後、私たちは彼を次のように変更しました.
このように変えてもだめで、私たちは少し苦境に陥って、それから彼に事務をしてあげたいと思って、私たちが望んでいるのではないかと思って、そこでまた次のように変えました.
少し进展して、そこでテストを行って、発见して、やはり时にはデータを见ることができて、时にはデータが见えないことがあって、これは、私达は接続数の问题かもしれないと思って、接続プールを変えて、何回のテストを経て、1つの接続しかない时、私达の望む情况を得ることができることを発见して、もし1つより大きい时、不确定な情况が现れます.私たちは多方面の実験を経て、接続プールに複数の接続があり、また私たちが望んでいる結果を得ることができないことを解決することはできません.そこで仕方がありません.無理をして、接続プールを再配置するしかありません.臨時表を使うときは、この接続プールを使って、修正が必要なDAOの場所で、私たちはDAOを再構築して、彼に元のDAOを継承させて、その中の相応の方法を修正します.コードに変更する上記のように、接続プールは私たち自身で組み合わせたもので、このような問題は解決された.接続プールの構成はoracle自身で直接使用します
問題の解決過程はこのようにして、今のところもっと良い方法が見つからないので、先にこのように解決して、もっと良い方法があれば上に書いてみんなで勉強してください.
次のプロジェクトで使用するコード:
select *
from (select rownum r_id, t_tmp.*
from (select p.*,
o.NAME_ZH,
o.NAME_EN,
o.NAME_JP,
o.ORG_DESC_ZH,
o.ORG_DESC_EN,
o.ORG_DESC_JP,
c.name_zh city_name_zh,
c.name_en city_name_en,
c.name_jp city_name_jp,
d.name_zh district_name_zh,
d.name_en district_name_en,
d.name_jp district_name_jp,
r.name_zh country_name_zh,
r.name_en country_name_en,
r.name_jp country_name_jp,
a.name_zh area_name_zh,
a.name_en area_name_en,
a.name_jp area_name_jp,
decode(t.propid,, 0, 1) isKeyHotel,
decode(s.propid,, 0, 1) isExchangeRateSet
from t_prop p,
t_city c,
t_country r,
t_district d,
t_area a,
T_PROPORG o,
t_keyhotel t,
t_prop_exchangerate_set s
where 1 = 1
and (p.prop = :1 or p.prop = :2 or p.prop = :3 or
p.prop = :4 or p.prop = :5 or p.prop = :6 or
p.prop = :7 or p.prop = :8 or p.prop = :9 or
p.prop = :10 or p.prop = :11 or p.prop = :12 or
p.prop = :13 or p.prop = :14 or p.prop = :15 or
p.prop = :16 or p.prop = :17 or p.prop = :18 or
p.prop = :19 or p.prop = :20 or p.prop = :21 or
p.prop = :22 or p.prop = :23 or p.prop = :24 or
p.prop = :25 or p.prop = :26 or p.prop = :27 or
p.prop = :28 or p.prop = :29 or p.prop = :30 or
p.prop = :31 or p.prop = :32 or p.prop = :33 or
p.prop = :34 or p.prop = :35 or p.prop = :36 or
p.prop = :37 or p.prop = :38 or p.prop = :39 or
p.prop = :40 or p.prop = :41 or p.prop = :42 or
p.prop = :43 or p.prop = :44 or p.prop = :45 or
p.prop = :46 or p.prop = :47 or p.prop = :48 or
p.prop = :49 or p.prop = :50 or p.prop = :51 or
p.prop = :52 or p.prop = :53 or p.prop = :54 or
p.prop = :55 or p.prop = :56 or p.prop = :57 or
p.prop = :58 or p.prop = :59 or p.prop = :60 or
p.prop = :61 or p.prop = :62 or p.prop = :63 or
p.prop = :64 or p.prop = :65 or p.prop = :66 or
p.prop = :67 or p.prop = :68 or p.prop = :69 or
p.prop = :70 or p.prop = :71 or p.prop = :72 or
p.prop = :73 or p.prop = :74 or p.prop = :75 or
p.prop = :76 or p.prop = :77 or p.prop = :78 or
p.prop = :79 or p.prop = :80 or p.prop = :81 or
p.prop = :82 or p.prop = :83 or p.prop = :84 or
p.prop = :85 or p.prop = :86 or p.prop = :87 or
p.prop = :88 or p.prop = :89 or p.prop = :90 or
p.prop = :91 or p.prop = :92 or p.prop = :93 or
p.prop = :94 or p.prop = :95 or p.prop = :96 or
p.prop = :97 or p.prop = :98 or p.prop = :99 or
p.prop = :100 or p.prop = :101 or p.prop = :102 or
p.prop = :103............................
.. or p.prop = :5443)
and p.countryid = r.countryid(+)
and p.cityid = c.cityid(+)
and p.areaid = a.areaid(+)
and p.districtid = d.districtid(+)
and p.ORGID = o.ORGID(+)
and p.prop = t.propid(+)
and p.prop = s.propid(+)
order by to_number(p.PROP)) t_tmp
where rownum <= :5444)
where r_id >= :5445
中にはN個以上のorがクエリ時の性能に影響しているので、この問題を解決する方法を考えます
問題の解決策:
テンポラリ・テーブルを使用して、これらのorの条件をテンポラリ・テーブルに挿入してから、コンビネーション・クエリーの方法で解決します.コンビネーション・クエリーは、これだけのorを使用するよりも速いです.
ソリューションの実行可能性分析:
仮表の特性によって、理論的には可能ですが、これらのものを変えるのは私たちのforcoreの枠組みの下に制限されているので、変えるのはそんなに簡単ではありません.次に、私のこの解決過程を書いて、もっと良い解決方法があるかどうかを検討します.
まず、Oracleテンポラリ・テーブルについて詳しく説明します.
Oracleテンポラリ・テーブルを作成します.2つのタイプのテンポラリ・テーブルがあります.
1.セッション・レベルのテンポラリ・テーブル
2.取引レベルのテンポラリ・テーブル
2つのタイプのテンポラリ・テーブルの違い:
セッションレベルのテンポラリ・テーブルはon commit preserve rowsを採用する.トランザクションレベルはon commit delete rowsを採用しています.使用法では、セッションレベルは、セッションが終了したテンポラリ・テーブルのデータのみが切断され、トランザクション・レベルのテンポラリ・テーブルはcommit、rollback、またはセッションが終了した場合にのみ、テンポラリ・テーブルのデータが切断されます.接続プールを使用しない場合は、jdbc接続を2つのタイプのテンポラリ・テーブルで実験します.接続プールに接続が1つしかない場合でも、目的の結果が得られます.この部分に関する試験コードは以下の通りである:表admin_work_areaはセッションレベルのテンポラリ・テーブルで、ここの接続プールは1つの接続のみを構成します.
public void testJDBC() {
try {
OracleDataSource ods = new OracleDataSource();
ods.setURL("jdbc:oracle:thin:@192.168.20.230:1521:FOG");
ods.setUser("fog");
ods.setPassword("fog");
ods.setConnectionCachingEnabled(true);
java.util.Properties jup = new java.util.Properties();
jup.setProperty("InitialLimit", "1");
jup.setProperty("MinLimit", "1");
jup.setProperty("MaxLimit", "1");
ods.setConnectionCacheProperties(jup);
Connection cx0 = ods.getConnection();
Statement stmt = cx0.createStatement();
stmt.execute("insert into admin_work_area(class) values ('1072')");
ResultSet rs = stmt.executeQuery("select * from admin_work_area");
while (rs.next()) {
String classId = rs.getString("class");
System.out.println(classId);
}
rs.close();
stmt.close();
Connection cx1 = ods.getConnection();
Statement stmt1 = cx1.createStatement();
// stmt1.execute("insert into admin_work_area(class) values ('1072')");
ResultSet rs1 = stmt1.executeQuery("select * from admin_work_area");
while (rs1.next()) {
String classId = rs1.getString("class");
System.out.println(classId);
}
rs1.close();
stmt1.close();
cx0.close();
cx1.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
問題の解決を開始:上記のような直接データベースに接続する試験コードを使って、私たちが想像していたように、この問題が解決しやすいと感じて、forcoreの中で直接修正しました.forcoreの中に接続プールが配置されているので、問題が発生しました.私たちが挿入したデータが見えます.私たちが挿入したデータが見えません.これは、使用する接続プールの接続が異なるためであり、接続プールの接続は破棄されません.繰り返しの試験とネット上で関連資料を探しても、使用時に1つの接続しか使用できないことを保証することはできません.毎回、接続プールに異なる接続を取ってもらうことはできません.デルのforcoreでは、DAO実装クラスの一般的なコードは次のとおりです.
public List selectAdminWorkArea(String classId){
List list = new ArrayList();
list = (List)getSqlMapClientTemplate().queryForList("tp.selectAdminWorkArea");
return list;
}
私たちが始めたとき、それを次のようにして臨時表を運用しました.
public List selectAdminWorkArea(String classId){
List list = new ArrayList();
getSqlMapClientTemplate().insert("tp.insertAdminWorkArea", classId);//
list = (List)getSqlMapClientTemplate().queryForList("tp.selectAdminWorkArea");
return list;
}
多くの部分は私たちがテンポラリ・テーブルにデータを挿入するために使用しています.次の文はテンポラリ・テーブルと組み合わせてクエリーするために使用されています.私たちのテンポラリ・テーブルはセッション・レベルで使用されています.私たちの考えでは、このように使用すればいいのですが、私たちが挿入したデータは、私たちが下で取るときには全然見えません.getSqlMapClientTemplate()を1つ使うたびに、彼は別の接続を取ります.その後、私たちは彼を次のように変更しました.
public List selectAdminWorkArea(String classId){
List list = new ArrayList();
SqlMapClient sqlMapClient = this.getSqlMapClient();
sqlMapClient.insert("tp.insertAdminWorkArea", classId);
list = (List)sqlMapClient.queryForList("tp.selectAdminWorkArea");
return list;
}
このように変えてもだめで、私たちは少し苦境に陥って、それから彼に事務をしてあげたいと思って、私たちが望んでいるのではないかと思って、そこでまた次のように変えました.
public List selectAdminWorkArea(String classId){
List list = new ArrayList();
SqlMapClient sqlMapClient = this.getSqlMapClient();
try{
sqlMapClient.startTransaction();
sqlMapClient.insert("tp.insertAdminWorkArea", classId);
list = (List)sqlMapClient.queryForList("tp.selectAdminWorkArea");
sqlMapClient.endTransaction();
}catch(Exception e){
System.out.println(e.getMessage());
}
return list;
}
少し进展して、そこでテストを行って、発见して、やはり时にはデータを见ることができて、时にはデータが见えないことがあって、これは、私达は接続数の问题かもしれないと思って、接続プールを変えて、何回のテストを経て、1つの接続しかない时、私达の望む情况を得ることができることを発见して、もし1つより大きい时、不确定な情况が现れます.私たちは多方面の実験を経て、接続プールに複数の接続があり、また私たちが望んでいる結果を得ることができないことを解決することはできません.そこで仕方がありません.無理をして、接続プールを再配置するしかありません.臨時表を使うときは、この接続プールを使って、修正が必要なDAOの場所で、私たちはDAOを再構築して、彼に元のDAOを継承させて、その中の相応の方法を修正します.コードに変更する上記のように、接続プールは私たち自身で組み合わせたもので、このような問題は解決された.接続プールの構成はoracle自身で直接使用します
<bean id="tp_dataSource" class="oracle.jdbc.pool.OracleDataSource">
<property name="URL" value="${datasource.url}" />
<property name="user" value="${datasource.username}" />
<property name="password" value="${datasource.password}" />
</bean>
問題の解決過程はこのようにして、今のところもっと良い方法が見つからないので、先にこのように解決して、もっと良い方法があれば上に書いてみんなで勉強してください.
次のプロジェクトで使用するコード:
public List<HotelInfoExcelVo> findHotelInfoExcelVoAll(HotelSearchVO hotelSearchVO) {
List<HotelInfoExcelVo> list = new ArrayList<HotelInfoExcelVo>();
List<String> props = new ArrayList<String>();
props = hotelSearchVO.getProps();
SqlMapClient sqlMapClient = this.getSqlMapClient();
Map map = new HashMap();
map.put("hotelSearchVO", hotelSearchVO);
map.put("tp_flag", "1");
try{
sqlMapClient.startTransaction();
sqlMapClient.startBatch();
for(int i = 0 ; i < props.size(); i ++){
String propId = props.get(i);
sqlMapClient.insert("Prop.insertTpPropid",propId);
}
sqlMapClient.executeBatch();
list = sqlMapClient.queryForList("Prop.findHotelInfoExcelVoAll", map);
sqlMapClient.endTransaction();
}catch(Exception e){
logger.error("class name TPDAO--method findHotelInfoExcelVoAll error!"+e);
}
return list;
}