Technology へようこそ
ここは技術者の「経験」と「ノウハウ」のブログです
2010年03月25日 |
バーチャル・カラム・パーティション |
Oracle Database 11g では、バーチャル・カラムを パーティション・キーとしてパーティション・テーブルを作成できます。 例) パーティション・キーを日付(yyyymmddhh24mmss形式の文字列)カラムの col_dateから月の部分を引用して'01'~'12'で振り分けた場合 --- テーブル作成最近携わった仕事では、 Oracle 10gを使用したシステムにおいて数百万件のデータが保持されるテーブルを パーティション・テーブルとして定義、パーティション・キーのカラムをchar(2)で設け、 データが持つ日付情報の日('01'~'31')にて振り分けるようにしています。 仮にOracle 11gであればバーチャル・カラムを設けてパーティション・キーとして 扱うことができたと思います。この場合、データを投入する側はパーティション・キーの カラムを意識せずにデータ投入できます。ただしINSERT文でカラムを明示的に指定している ことが前提となります。またバーチャル・カラムを用いた場合のINSERTに掛かる負荷が どの程度か検証は必要かと思います。 [ posted by kami ]
スポンサーサイト
|
2009年07月24日 |
クエリー・リライト |
マテリアライズド・ビューを作成すると初期化パラメータのguery_rewrite_enabledが 標準値(TRUE)となっている場合にクエリー・リライト機能が利用できます。 クエリー・リライト機能とは、SQL文でマテリアライズド・ビューの参照元テーブルを 検索する場合、参照元テーブルを検索する場合のコストとマテリアライズド・ビューを 検索する場合のコストを比較し、マテリアライズド・ビューを検索した方が コスト的に低いと判断された場合、SQL文が自動的に変換されるというものです。 マテリアライズド・ビューとはSELECT文の結果を保存する オブジェクト(セグメントを保持する永続オブジェクト)です。 作成例) create materialized view sample_mvマテリアライズド・ビューの参照元テーブルとマテリアライズド・ビューの同期は リフレッシュ処理で取ります。クエリー・リライトの初期化パラメータquery_rewrite_integrityの 標準値(enforced)では整合性が保障され同期が取れている場合のみリライトが行われます。 仕事ではマテリアライズド・ビューを作成するシチュエーションがありませんでしたが 使う機会があればこういった機能も考慮しておきたいです。 [ posted by kami ]
|
2009年05月19日 |
DB設計時の冗長項目について |
DB設計する際、よく正規化、正規化といわれます。 正規化はRDBにおいて、データの一貫性の維持と効率的なデータアクセスを 可能にするための方法論のことですが、冗長にもよい場合があって、たとえば、 会計システムの伝票テーブルなどは伝票行で1レコード、しかもヘッダ項目も そのなかに含まれる形式のものが多く、冗長である(つまり第1正規化しか行 われいていない)と言えるのですが、これはデータの取り回しがよいためで、 正規化がベスト!というわけではないのが現実です。 よくベンダ系の試験なんかで見かけるものだと、DWHのアクセス効率をよく するためにはどうすればよいか?という問いに対し、 1.ビットマップインデックスを付ける 2.オプティマイズヒントを用いる 3.合計項目を追加する 4.トリガを用いる この選択肢では、3.合計項目を追加する(冗長化する)というのが答えになるわ けです。DWHでは特に、データは追加のみで更新などはほとんど起こらない ことを前提にしますから、ここがポイントなわけです。 ところが、DWHではないDBで伝票形式で冗長性を持たせた場合にネックに なる項目があります。 「伝票合計」です。1行でも変更があった場合、6行の伝票なら本来1行の修正で すむところが6行分の更新が必要になります。 ORACLEにはROLLUPという便利なキーワードがあって、GROUP BY句に使用すること で、1回のSQLで小計、合計を計算することができます。 ただ、検索結果が合計行として行追加されてくるのが難点。つまり、対象件数が 1件であっても、複数件返ってくるのです。簡単なレポートのデータ検索なんかには よいかも。 SELECT TABLE1.COL1, TABLE2.COL2, SUM(TABLE3.COL3) パフォーマンスはまあまあ。 通常のときはGROUP BY で結果セット(合計値)とって、ふつうにINNER JOIN したほうがラクなんですけどね。 [ posted by H.K ] |
2009年04月17日 |
バーチャル・カラム |
Oracle Database 11g では、 テーブルにバーチャル・カラムを定義できます。 例) create table sample_table ( 2007年10月31日掲載の(SQLServer2005)「機能強化されたDDLステートメント」と 似たような感じはしますが、こちらはビューを作るほどでもないような 計算式を埋め込むのに利用すると便利です。 [ posted by kami ]
|
2009年04月01日 |
CPU負荷の低いバッチ処理 |
「CPU負荷の低いバッチ処理ってあるんですかねえ・・・。」 通常、バッチ処理なんかは運用時間中のレスポンス性能を考えた場合、 誰も使用していない時間帯に実行する(いわゆる、夜間バッチってやつ) ようにしたり、日中バッチが実行される必要性がある場合などには、「 今からバッチ流します。遅くなりますよ~」なんていうアナウンスを したりするもんです。 ところが、今係わっているシステム、タイマー起動でバッチが流れるの ですが、CPU負荷が低いらしく、いつやっているのかわからない。 よくある話で、バッチスケジュールのドキュメントが未整備で公開され ていないので、あたりを付けるのにCPU負荷をトレースしたが、なんか ピンとこない。そこで冒頭のQになったわけですが、 「ありますよ。ループで処理されている場合は低くなりがちですね。」 という訳で、簡単なサンプルを作成してやってみました。 DBはOracle10g、AIX版です。 65万件のトラン中、50件程度の件数をアップデート。 1つはループ処理、もうひとつは一括更新。 CPU負荷をタスクマネージャで見てみました。ついでに実行時間も。 ・ループ処理(レコードロック有り) CPU負荷は以下のとおり。実行時間:1分47秒(45/650,000件更新) ![]() ・一括更新処理(レコードロック有り) CPU負荷は以下のとおり。実行時間:2秒(45/650,000件更新) ![]() ちなみに 50,000/650,000件更新は一括で9秒。 ![]() また 300,000/650,000件更新は一括で24秒でした。 ![]() Oracleのループ処理って、速いイメージだったのですが。 意外にもOracleのループ処理はそんなに速くない。 [ posted by H.K ]
|
2009年02月27日 |
CONTINUE文 |
Oracle 11g ではPL/SQLプログラム中で ループを制御するCONTINUE文が記述できるようになったそうです。 例) declareループ処理中に特定のタイミングでスキップできるのは IF文などで分岐するより便利で使い勝手がよさそうです。 [ posted by kami ]
|
2008年12月22日 |
HASH |
SQLでテーブルをJOINする際には、テーブルの結合方法として NEST LOOP結合、MERGE結合、HASH結合の3つがあるのですが、 どうもORACLEのオプティマイザはNESTED LOOPSを使いたがる 傾向があるようで・・・。 何も指定しないとほとんどNESTED LOOP。これってどうなんで しょう?私が使っている環境だけ? 同じ件数同士のテーブルを結合する際は一般にHASHの方が速い ということが言われますが、(MERGEはORDER BYの分、不利だ とも・・・)ヒントは SELECT /*+ USE_HASH(TABLE_A TABLE_B) +*/ ・・・ てな具合に指定します。 ただし、注意が必要なのは「同じ件数同士」でも 1.テーブル自体の件数が同じ 2.where条件適用後の件数が同じ ではまるで違います。ここで言うところの「同じ件数」は2.の ほうなので、「HASHのほうが速いはずだよ。きっと。」と、ヒン トを指定。すると30秒かかっていたSELECT文が0.5秒に。 ところが・・・同じSQLが異なる環境で「遅い。」という結果が。 SQLDeveloperで実行プランを見ると、HASHですねえ。確かに。 はあ、1分もかかってます。こりゃだめですねえ。 そんじゃまあ、ヒント、変えてみますか。どうなるの? あ!っという間に終了。0.5秒です。NESTED LOOPだわ。やっぱり。 しかしまてよ。指定しないほうがいいんじゃないか。という考え がよぎり、ノーヒントで実行。実行プランはNESTED LOOP。0.5秒。 とりあえず、オプティマイザまかせにしよう、ということに。 「転ばぬ先の杖」だったはずが「蛇足」になってしまいました。 ヘタにヒント使うと思わぬしっぺ返しをくらいます。 ちなみに私はNESTED LOOP信者です。 [ posted by H.K ]
|
2008年10月30日 |
NULL値の整列順 |
OracleにおいてNULL値を含む項目をORDER BY句で昇順(ASC)指定したい場合、 通常、NULL値は最後(≒無限大)になってしまいます。降順指定ではもちろん 最初になります。 Oracle 8.1.6 以上であれば、オプション指定により昇順の場合に最初に持 って来れたりします。 例) ORDER BY 項目名 NULLS FIRST 御想像のとおり最後に持ってくるのは NULLS LAST というオプションです。 SQLServerでこれをやるなら Isnull関数を使うのが手っ取り早いかなぁと 思います。 ORDER BY句のオプション指定は他にもいろいろあります。 でも、そもそもnull許容項目において昇順にしたいなんていうのは仕様が おかしいのではないか。なかにはプライマリキー項目でnull許容がしたい などと言う輩が居たりするのはほんとうに嘆かわしい。(できねえよ!) 相変わらず、DB設計はおざなりにされているようですねぇ。 みなさんの会社ではどーですか? [ posted by H.K ]
|
2008年10月21日 |
Oracleの便利なスクリプト |
ステータスがINVALIDのオブジェクト システムを運用いく上で、表やビュー、プロシージャなどを削除/再作成/定義変更することがあると思います。変更などのあったオブジェクトを参照するビューやプロシージャは無効(INVALID)状態となり、次回アクセス時に再コンパイルされます。 こうして無効状態となったオブジェクトが存在しないか調査し、必要であれば対策を講じます。 Oracleでは、再コンパイルによって有効(VALID)状態に戻る無効(INVALID)状態のオブジェクトに関して、一括で再コンパイルを実行できるスクリプトが標準で用意されています。 ◆スクリプト: utlrp.sql , utlirp.sql (処理内容はどちらも同じ) ◆スクリプトの場所: UNIX/LINUX --- $ORACLE_HOME/rdbms/admin WINDOWS --- %ORACLE_HOME%\rdbms\admin ◆スクリプトの内容: FUNCTION,PACKAGE,PACKAGE BODY,PROCEDURE,TRIGGER,VIEWの各オブジェクトに再コンパイルを実行する。 ◆スクリプトの使用例: (SYSユーザーで実行する) C:\>sqlplus /nolog SQL> connect / as sysdba SQL> @%ORACLE_HOME%\rdbms\admin\utlrp.sql 表の再作成などで、無効(INVALID)状態になるオブジェクトが多数発生してしまう場合などに使用すると便利です。 [ posted by h.i ]
|
2008年09月16日 |
Oracle監査 |
結合テスト中、一瞬にしてデータが消えました。 作業ステータスを管理するテーブル。約30万件。Object Browserで確認 するとテーブルの更新日付のみ変更されています。ということは、 TRUNCATEでばっさり誰かがテーブルのデータを切り捨てたことになります。 (DROP→CREATEでは作成日付も変更され、作成日付=更新日付になる) 幸い、バックアップからデータを戻すことができたため、難は逃れましたが、 犯人は不明。 DBの監査を行うことにしました。 対象はDDL文。つまり今回の事件を教訓として CREATE,ALTER,DROP, TRUNCATEなどを実行した記録を取ろうというわけです。 systemユーザでログインします。 ログはOS上のファイルとして書き出し、出力フォルダを指定します。 alter system set AUDIT_TRAIL=OS scope=SPFILE; 監査対象ユーザに権限を与えます。 grant audit system to (ユーザ名); 監査を開始。 audit table; -- 監査の開始 監査を止める場合は・・・。 noaudit table; -- 監査を止める DDL文が発行されるとログ出力されることを確認。アクションが数値でロギングさ れます。その種類は? -- 操作の種類がわかる つまり、TRUNCATE TABLE なら ACTION=85 というわけです。 [by H.K] |
|