2015年3月8日日曜日

SQLパフォーマンスへのチェックポイント


大文字/小文字/空白や改行の数を統一する

  処理内容が同じSQLでも、大文字/小文字/空白や改行の数が異なると、別々にキャッシュされてしまい、解析済みのSQLが共有されなくなるので、その分パフォーマンスが低下する。

  SQLのコーディング方法を統一して、キャッシュ上で共有されるようにしましょう。

下記4つのSQLは、処理内容は同じですが、それぞれ、メモリ上にキャッシュされ、再利用されません。
大文字/小文字/空白や改行の数は異なるので、違うSQLと解釈される。
 select * from dept;

 select * from DEPT;

 select   * from dept;

 select *
     from dept;

バインド変数を使用する
  SQLで、変数の値を設定する場合は、バインド変数を使用することによって、SQLが共有されます。
 ○ select * from dept where dept_id = :dept_id;

 × select * from dept where dept_id = 'D001';

SELECT * は使用しない
  SELECTで*を使用すると、解析/IOともにパフォーマンスが低下するので、必要な項目のみ指定します。
 ○ select dept_id, dept_name from dept;

 × select * from dept;

SELECT COUNT(*)は使用しない
  COUNT関数を使用する時は、COUNT(列名)で指定する。
  但し、COUNT(列名)は、指定した列がNULLの場合は、カウントしないので、プライマリキー項目などのNOT NULL列を指定する。
 ○ select count(dept_id) from dept;

 × select count(*) from dept;

ANDよりBETWEENの使用を検討する
  BETWEENは、指定された範囲評価の操作が1回で済むのに対し、ANDは複数回の操作となるので、ANDよりBETWEENの使用を検討する
 ○ select * from emp where salary between 0 and 3000;

 × select * from emp where salary >= 0 and salary <= 3000;

HAVINGよりWHEREの使用を検討する
  HAVINGは非常に重い処理なので、集計結果の判定以外は、HAVING句よりWHERE句の使用を検討する。
 × select dept_id, sum( salary ) from emp group by dept_id having dept_id = 'D02';

 ○ select dept_id, sum( salary ) from emp where dept_id = 'D02' group by dept_id;
UNIONよりUNION ALLの使用を検討する

  UNIONはSELECTの結果をマージした後に、暗黙のソート処理をして重複データを排除しますが、重複データが無いことが分かっている場合は、暗黙のソート処理を回避するために、UNION ALLを使用する

  ※UNIONの他にも、DISTINCTや、GROUP BY、INTERSEST、MINUS等にも暗黙のソート処理が実行されるので、極力使用を避けた方が良い。


テーブルに別名を付ける
  テーブルに別命を付けると、解析速度が向上するので、別名を付けるようにする
 ○ select a.emp_id, a.emp_name from emp a;

 × select emp_id, emp_name from emp;

ROWIDの使用を検討する

  ROWIDとは、データベース内のレコードのアドレスを表すOracleの内部的な管理情報です。
  その為、WHERE句にROWIDを使用すると、テーブルのレコードに最速でアクセスできます。

  但し、Export/Importや表の移動(alter table moveコマンド)などでROWIDは変更されてしまう為、ROWIDの使用は、SELECTでデータを取得後に再度アクセスする場合などに限定されます。

 例)データを検索して、そのレコードを更新する。
 select emp_id,salary,rowid from emp;

 update emp set salary = 250 where rowid = 'AAAF+OAAIAAABmMABL';
列番号は使用しない
  ORDER BY句に列番号で指定した場合、SQL解析時に読み替え処理が発生するのでパフォーマンス低下に繋がる
 ○ select a.emp_id, a.emp_name from emp a order by salary;

 × select a.emp_id, a.emp_name from emp a order by 5;

DISTINCT句よりEXISTS句の使用を検討する

  DISTINCTは、条件に一致するレコードを取り出し暗黙のソート処理後に重複レコードを排除することに対し、EXISTS句は条件に一致するレコード1件でもあればそこで処理は終了する為、暗黙のソート処理をしない分、DISTINCTに比べると負荷が小さくなる
 × select distinct a.emp_id, a.dept_id from emp a,dept b
            where a.dept_id = b.dept_id;

 ○ select a.emp_id, a.dept_id from emp a
       where exists (select 'X' from dept_b where a.dept_id = b.dept_id);
 ※DISTINCTの他にも、GROUP BYやUNION、INTERSEST、MINUS等は暗黙のソート処理が実行されるので、極力使用を避けた方が良い。

NOT IN句よりNOT EXISTS句の使用を検討る

  NOT IN句は、内部的にソートマージの結合をすることでテーブルをフルスキャンするのに対し、NOT EXISTS句は条件に一致するレコード1件でもあればそこで処理は終了する為、NOT IN句に比べると負荷が小さくなる
 × select distinct a.emp_id, a.dept_id from emp a
    where a.dept_id not in (select b.dept_id from dept where job_id = 'J01');

 ○ select a.emp_id, a.dept_id from emp a
   where not exists (select 'X' from dept_b where a.dept_id = b.dept_id and job_id = 'J01');
INDEX列で論理比較のNOTの使用は、INDEXが使用されない。
 × select * from emp where emp_id <> 'E01';

 × select * from emp where emp_id not in ('E01','E02','E03');

INDEX列で関数の使用は、INDEXが使用されない。
  Bツリー・インデックスで関数を使用すると、INDEXが使用されない。
  但し、ファンクション・インデックスを作成した場合は関数が使用できる。
 × select * from emp where substr(emp_id,1,1) = 'E';


INDEX列で演算子の使用は、INDEXが使用されない。
 ○ select * from emp where salary > 100;

 × select * from emp where salary - 50 > 100;


INDEX列でNULL比較の使用は、INDEXが使用されない。
  Bツリー・インデックスの中にはNULL値は存在しないので、WHERE句に「IS NULL」を指定するとINDEXは使用されない。
  但し、ビットマップ・インデックスの場合は、NULL値はインデックスに含まれるので、INDEXは使用される。
 × select * from emp where emp_name is null;

INDEX列でLIKEは前方一致以外は、INDEXが使用されない。
 ○ select * from emp where emp_id = 'E00%';

 × select * from emp where emp_id = '1';

 × select * from emp where emp_id = '%';

ORDER BY句の指定列が全てINDEXに指定ないと、ソートにINDEXが使用されない。

 ORDER BY 句で指定する項目は、全てINDEXに含まれ、かつ、NOT NULL項目の場合は、高速にソートされます。

暗黙の型変換は、INDEXが使用されない。
  WHERE句で指定した、列の型とデータの型が異なる場合、ORACLEは自動的に型変換を実行するが、型を自動変換する場合はINDEXが使用されない。
     dept_id が cahr型で定義されている場合
 × select * from dept where dept_id = 123;

 ○ select * from dept where dept_id = '123';

複合INDEXは先頭列から指定しないと、INDEXが使用されない。
   以下の順番で複合INDEXを作成
 (1)emp_id
 (2)dept_id
 (3)job_id

  上記の複合INDEXの場合の、INDEXの使用/未使用となるWHERE句パターン
 ○ select * from emp where emp_id = 'E01' and dept_id = 'D01' and job_id = 'J01';

 ○ select * from emp where emp_id = 'E01' and dept_id = 'D01';

 ○ select * from emp where emp_id = 'E01' and job_id = 'J01';

 ○ select * from emp where emp_id = 'E01';

 × select * from emp where dept_id = 'D01';

 × select * from emp where job_id = 'J01';

 × select * from emp where dept_id = 'D01' and job_id = 'J01';

2015年2月9日月曜日

コミュニケーションパス

コミュニケーションパスを算出する式です。

総パス数 = n(n-1)/2

関与可能パス数 = n-1

例としては

人数 総パス数 関与可能バス数 シェア
 10   45       9 20.0%
 20  190      19 10.0%
 50 1225      49  4.0%
100 4950      99  2.0%



2015年1月20日火曜日

EclipseでAPPを起動し、メモリ不足問題の解消

■問題 EclipseでAPPをDEBUG方式で起動するとき、メモリ不足エラーが出てきます。


eBuilder8配下のeBuilder8.iniにて、最大メモリは1024Mに設定しました。
-Xms512m
-Xmx1024m

resin\conf\resin.propertiesにて、最大メモリは2048に設定しました。
jvm_args  : -Xmx2048m -XX:MaxPermSize=4028m


EclipseでAPPを起動するとき、ずっとメモリ不足エラーが出てきます。

■対応方法

サーバータブ→Debug Server(Resin V4.0) をダブルクリックして、

サーバー概要で 「起動構成を開く」→引数タブ

VM引数

Djp.co.intra_mart.system.debug.DebugServer="cJI5vEAzPrPonvFjIXd3u65U0UlkPsipKSAgP7fNxF1baQixbT2ZNO7CWq/tdM8eZcpt19ATMtk="
      -Djp.co.intra_mart.system.javascript.Debugger.port="9000"
      -Xss1m -Xmx128m -Xms512m -XX:MaxPermSize=512m -server
      -Djava.library.path="C:/biz_integral/resin/win64;"


下記のように変更すれば、DEBUG環境のメモリ不足の問題は解消できます。

-Xss1m -Xmx2048m -Xms1024m -XX:MaxPermSize=1024m

2014年12月18日木曜日

オラクル ロック解除


データをテーブルにインサートするとき、反応がない。

SQL自体は問題ないことを確認したあと、もしかしてロックのせいかなと思っている。

ロックとは、ある処理がコミットされずに、その後に続く処理が待ち状態になってしまっていること。

対応手順は下記となります。

SQL> SELECT SID, SERIAL# FROM V$SESSION
  2  WHERE SID IN (
  3  SELECT SID FROM V$LOCK
  4  WHERE TYPE IN ('TM','TX')
  5  );

       SID    SERIAL#
---------- ----------
        30      49247
        74      47697

SQL> alter system kill session '30,49247';

システムが変更されました。

SQL>
SQL> alter system kill session '74,47697';

システムが変更されました。

SQL> SELECT SID, SERIAL# FROM V$SESSION
  2  WHERE SID IN (
  3  SELECT SID FROM V$LOCK
  4  WHERE TYPE IN ('TM','TX')
  5  );

レコードが選択されませんでした。

SQL>

PL/SQLプロシージャのコンパイル時フリーズになる

PL/SQLプロシージャのコンパイル時フリーズになる

フリーズしたセッションが応答待ちのままになっているためです。

停止するセッションを識別するには、フリーズしてしまったセッションの索引番号とシリアル番号を指定します。
セッションのシステム識別子(SID)とシリアル番号を識別するには、V$SESSION動的パフォーマンス・ビューを問い合せます。

SELECT
    SID ,SERIAL# ,STATUS
FROM
    V$SESSION
WHERE
    USERNAME = 'LEON_TENANT';



       SID    SERIAL# STATUS
---------- ---------- --------
        40          1 INACTIVE
        42       2493 ACTIVE


ALTER SYSTEM KILL SESSION '42,2493';

再度コンパイルを実施すると、無事にコンパイルことはできました。

2014年12月3日水曜日

resin deploy timeout 解消

問題:

>resin deploy imart.war
java.lang.IllegalStateException: QueryFutureCallback[] future timeout: 120000ms


解決方法:
%resin_home%/resin.properties のdependency_check_interval を-1に変更する。

# dependency_check_interval : 5m
dependency_check_interval : -1


resinを再起動する。

resin deploy を実施する。

2014年12月2日火曜日

Oracleスキーマ単位にExport


1.準備

C:\verup>sqlplus system/password@127.0.0.1:8521/orcl

SQL*Plus: Release 11.2.0.1.0 Production on 火 12月 2 10:00:58 2014

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
に接続されました。
SQL>
SQL>

ダンプファイル(Exportしたファイルのこと)とログを格納するディレクトリを作成。

SQL> create directory dumpdir as 'c:\verup\dump';

ディレクトリが作成されました。

SQL> create directory logdir as 'c:\verup\log';
ディレクトリが作成されました。

Oracleのユーザにディレクトリに読み書き権限を与える。
SQL>grant read,write on directory dumpdir to biz_one;
権限付与が成功しました。

※上記のコマンドを実行しないと、ORA-39070が発生しますよ。
ORA-39070: ログ・ファイルをオープンできません。

ディレクトリ・オブジェクトの確認
SQL>set pagesize 0;
SQL>select * from dba_directories;

2.Exportコマンドを投入

expdp dbuser/password@orcl schemas=biz_one directory=dumpdir dumpfile=biz_one_20141202.DMP

3.Import コマンドで導入

impdp new_user/password@orcl directory=dumpdir remap_schema=biz_one:biz_two dumpfile=biz_one_20141202.DMP

4.export 時と異なるスキーマ、異なる表領域に import
impdp user/password@orcl directory=dumpdir remap_schema=old_schema:new_schema dumpfile=xxxx.DMP remap_tablespace=old_tablespace:new_tablespace