パフォーマンス重視のDB2 SQLコーディング:基礎

Craig Mullins, Director of Technology Planning , BMC Software

Craig S. Mullins氏は、BMC Software (テキサス州ヒューストン) のテクノロジー計画ディレクター。氏はDB2、Oracle、SQL Serverを含む複数のデータベース管理システムにアプリケーション開発者、DBA、およびインストラクターとして従事した経験があり、データベース管理分野で広範な実績を有する。以前は、Gartner Groupにおいてデータベース管理分野を網羅するリサーチ・ディレクターを務める。DB2 for OS/390に関する業界最先端の書籍『DB2 Developer's Guide』の著者であり、2002年6月には、最新の著書『Database Administration: Practices and Procedures』がAddison-Wesley社より出版された。さらに、www.dbazine.comにも、編集者および常時コラムニストとして貢献している。『Database Trends & Application』誌に毎月「DBA Corner」コラムを、また『The Database Administration Newsletter』ポータルに四半期ごとの「Database Report」コラムを執筆中。



2002年 10月

技術情報の検索はこちらからIBMの情報管理テクノロジーを学ぶための100の情報
技術情報の検索はこちらから

はじめに

IBM DB2® Universal DatabaseTM(DB2 UDB) とBorland® 社のツール (DelphiTM、C++BuilderTM、KylixTMなど) を使用して作成されたエンタープライズ・アプリケーションを最高のパフォーマンスで稼働させるためには、DB2のオプティマイザーが非常に有効です。オプティマイザーは、非効率なSQLステートメントでさえ、効率的なアクセスパスを見つけ出し、高速処理を可能にします。とはいえ、稚拙に書かれたSQLやアプリケーション・コードには、いくつかの基本的ガイドラインを習得することによって簡単に回避できるパフォーマンス上の問題が存在します。本ガイドでは、DB2オプティマイザーの仕組みを示し、オプティマイザーを最大活用するSQLを作成する際のガイドラインを解説します。しかし、DB2のオプティマイゼーション能力をもってしても、効率的SQLステートメントの作成は難しい作業です。このことは、リレーショナル・データベース環境に不慣れなプログラマーや開発者には特にあてはまります。したがって、パフォーマンスを重視したSQLコーディングの詳細の検討に入る前に、まずSQLの基礎を見直してみましょう。


基礎

SQLでは高度な抽象化が行われるため、プロシージャー言語とは異なり、プログラマーは必要となるデータが何なのかに注力をすればよく、そのデータをどのようにとってくるかを気にする必要はありません。プロブラマーは、データナビゲーション命令を書く必要はなく、SQLだけをコードすればよいのです。DB2がSQLを分析し、舞台裏でナビゲーション命令を組み立てるからです。これらのデータ・ナビゲーション命令はアクセス・パスと呼ばれます。データへの最適なアクセス・パスをDBMSに決定してもらうことで、プログラマーは重荷から解放されます。さらに、データベースも保管するデータの状態をより正しく把握することができ、データへの一層効率的で動的なアクセス・パスを生成できます。その結果、SQLが正しく使用され、アプリケーション開発を加速できます。

もう1つのSQLの特性は、データを操作する照会言語以外に他の用途にも使用されるということです。データ構造の定義、データへのアクセス制御、およびデータのオカレンスの挿入、変更、削除にも使用できます。SQLという共通言語を提供することにより、SQLはDBA、システム・プログラマー、アプリケーション開発者、システム・アナリスト、およびエンドユーザー間のコミュニケーションを円滑にします。プロジェクトに参画するすべての関係者が同じ言語を使うとき、シナジーが生まれ、全体的なシステム開発時間が短縮されます。

議論の余地もありますが、SQLが広く支持されているのはSQLが英語によく似た構文を使用して容易にデータを検索できるからです。何ページものソース・コードを理解するより、この構文を理解する方がはるかに簡単です。

SELECT  LASTNAME
FROM    EMP
WHERE   EMPNO = '000010';

次の状況を考えてみてください。ファイルからデータをアクセスする際、全てプログラマーが命令をコーディングしなければならないとします。たとえばファイルを開き、ループを開始し、レコードを読み取り、EMPNOフィールドが適切な値に等しいかどうか調べ、ファイルの終わりを調べ、ループの始めに戻り、・・・など何もかもです。

SQLは本来、極めて柔軟です。自由形式の構造を使用するので、ユーザーは自身のニーズに合わせてSQLステートメントを開発できます。DBMSは実行に先立って各SQL要求を解析して適切な構文を調べ、要求を最適化します。SQLステートメントは特定のカラムで開始する必要はなく、ストリングを1行にまとめたり、数行に分割することもできます。たとえば、次の単一行SQLステートメントは、前述の3行の例と同等です。

SELECT LASTNAME FROM EMP WHERE EMPNO = '000010';

SQLのもう1つの柔軟な特性は、1つの要求を、形は異なるが機能的には同等のいくつかの方法で構築できることです。たとえば、SQLでは表の結合や照会のネストができます。ネストされた照会は常に1つの同等の結合に変換できます。この柔軟性の例は、他にも広範囲の関数や述部に見られます。同等の機能性を持つ機能には、たとえば次のような機能があります。

  • BETWEEN vs. <= / >=
  • IN vs. ORで結びついた一連の述部
  • INNER JOIN vs. FROM文節で、カンマ区切りでつなぎ合わされた表
  • OUTER JOIN vs. UNIONを使用した単純なSELECTと相関する副選択
  • CASE式 vs. 複雑なUNION ALLステートメント

形は異なるが機能的に同等のSQLを作成した場合に著しくパフォーマンスが異なることがあるので、SQLが示すこの柔軟性は常に望ましいものであるとは限りません。柔軟性の派生効果については後述し、効率的SQLの開発のためのガイドラインを提供します。

前述のとおり、SQLでは検索対象や操作対象のデータを指定しますが、どのように行うかは指定しません。このため、SQLは本質的にシンプルです。リレーショナル・データベースがセット指向であることを思い出せば、SQLの本質と特性を把握できます。1つのSQLステートメントが複数の行に作用できます。一連のデータに作用できる機能と、データの検索および操作方法の確立が不要であることを組み合わせると、SQLは非プロシージャー言語として定義されます。

SQLは非プロシージャー言語なので、1個のステートメントで何行ものプロシージャーの内容を書き表すことができます。これも、SQLがセット・レベルの処理を用い、DB2が照会を最適化してデータ・ナビゲーション・ロジックを判断するので、可能になります。時には、プロシージャ言語で記述されたプログラム全部と同等の機能を、1つか2つのSQLだけで実行することもできます。


オプティマイザー

オプティマイザーはDB2の核心部です。SQLステートメントを分析して、各ステートメントに対するもっとも効率的なアクセス・パスを決定します (図1参照)。DB2 UDBでは、SQLステートメントを解析してアクセスすべき表と列を判断します。続いてDB2オプティマイザーは、システム情報と、DB2システム・カタログに保管されている統計情報を照会し、SQL要求を満たすために必要なタスクの遂行に最適な方法を決定します。

図1. 作動中のDB2オプティマイゼーション
図1. 作動中のDB2オプティマイゼーション

オプティマイザーは機能的にはエキスパート・システムと同等です。エキスパート・システムは標準ルールのかたまりであり、与えられた状況データをルールに適合させ「エキスパート」の意見を導き出します。たとえば、医療のエキスパート・システムは、どの薬品がどの病気に有用であるか判断するルール群をもち、数々の病気の症状のデータ群と組み合わせて知識データベースを作ります。そして、その知識ベースに症状を入力し、結果を求めるのです。DB2オプティマイザーは、DB2のシステム・カタログに保管された統計情報とSQL形式の照会入力に基づいて、データ検索方法に関するエキスパートの意見を返します。

DBMSにおけるデータ・アクセスを最適化するという考えは、DB2のもっとも強力な能力の1つです。DB2に対して検索方法ではなく何を検索するかを指示することによって、DB2データをアクセスするということを思い出してください。データの物理的な保管方法や操作方法には関係なく、DB2とSQLはそのデータをアクセスできます。アクセス条件を物理的な保管特性から切り離すことを、物理データの独立性と呼びます。DB2のオプティマイザーは、この物理データの独立性を実現したコンポーネントです。

索引を除去しても、DB2は依然としてデータをアクセスできます (ただし効率は低下します)。アクセス対象の表に列を追加すると、DB2はプログラム・コードを変更しなくても、依然としてデータを操作できます。このようなことがすべて可能になるのは、DB2データへの物理アクセス・パスが、プログラマーによってアプリケーション・プログラム中にコーディングされたものではなく、DB2によって生成されたものであるためです。

これを、プログラマーがデータの物理構造を知らなければならない非DBMSシステムと比べてみてください。索引があれば、プログラマーは索引を使うために適切なコードを作成する必要があります。誰かが索引を削除すると、プログラマーが変更しない限り、プログラムは機能しません。DB2およびSQLでは違います。この柔軟性のすべては、データ操作要求を自動的に最適化するDB2の能力に帰するものです。

オプティマイザーは、多くの情報に基づいて複雑な計算を実施します。オプティマイザーの動作の仕組みをビジュアルにイメージするには、オプティマイザーを次の4ステップに分けて、プロセスを考えてみましょう。

  1. SQLステートメントの構文を受け取って検証する
  2. 環境を分析し、SQLステートメントを満たす方式を最適化する
  3. 最適化されたSQLを実行するための機械可読命令を作成する
  4. 命令を実行するか後の実行のために保管する

もっとも興味深いのは、このプロセスの第2ステップです。プログラマーが作成し得る膨大なSQLステートメントの実行方法を、オプティマイザーはどのように決定するのでしょうか?

オプティマイザーはSQLを最適化するための多くの種類のストラテジーを持っています。オプティマイザーは、最適化されたアクセス・パスでどのストラテジーを使用するかをどのように選択するのでしょうか? IBMは、オプティマイザーによる最良アクセス・パスの決定方法の、実際の詳細を公開していませんが、オプティマイザーはコスト・ベースです。これはすなわち、オプティマイザーは常に、各照会に対して、全体的なコストを小さくするアクセス・パスの構築を試みるということを意味します。これを実現するために、DB2オプティマイザーは照会コスト式を適用します。この式で、CPUコスト、I/Oコスト、DB2システム・カタログ内の統計情報、および実際のSQLステートメントという4つの要因を候補となるアクセス・パスのそれぞれに対して評価して重み付けします。


パフォーマンスのガイドライン

そこで、DB2オプティマイザーに関する情報を念頭に置き、SQLパフォーマンスの向上のためのガイドラインについて解説します。

1)DB2統計情報を最新に保つ: DB2のシステム・カタログに統計情報が保管されていない場合、オプティマイザーにとって、最適化処理が難しくなります。統計情報には、アクセス対象の表に関する様々な情報が保持されており、オプティマイザーは、これを使ってSQLを最適化します。システム・カタログに保管される統計情報には、次のような種類の情報があります。

  • についての情報。総行数、圧縮に関する情報、および総ページ数
  • についての情報。列の離散値の数や列に保管された値の分散範囲
  • 表スペースについての情報。アクティブ・ページの数
  • 現在の索引ステータス。索引が存在するか否か、索引の編成 (リーフ・ページ数とレベル数)、索引キーの離散値の数、クラスター索引か否か
  • 表スペースと索引ノード・グループまたは区画についての情報

統計情報は、RUNSTATSまたはRUN STATISTICSユーティリティーを実行したときにDB2システム・カタログに保管されます。このユーティリティーは、コントロール・センターからか、バッチ・ジョブ、あるいはコマンド行プロセッサーを使用して起動できます。特に本番環境では、必ずDBAの協力のもと、適切なタイミングで統計情報を蓄積してください。

2) 適切な索引を作成する: 最高のDB2アプリケーション・パフォーマンスを保証するためにユーザーができるもっとも重要なことは、アプリケーションで使用する照会に基づいて、表に対する正しい索引を作成することです。もちろん、実行は言うほどには容易ではありません。しかし、基本的なことから開始できます。たとえば、次のSQLステートメントを考えてみます。

SELECT   LASTNAME, SALARY
FROM     EMP
WHERE    EMPNO = '000010'
AND      DEPTNO =  'D01'

この単純な照会には、どのような索引 (複数可) が適切でしょうか? 最初に、作成し得るありとあらゆる索引について考えてみます。すぐに思いつくのは、おそらく次にリストした索引でしょう。

  • EMPNOにIndex1
  • DEPTNOにIndex2
  • EMPNOとDEPTNOにIndex3

手始めとしては上々です。この中ではIndex3がおそらく最良です。Index3を使うと、DB2はWHERE文節にある2つの単純な述部を満たす行を即座に検索できます。もちろん、EMP表にすでに多くの索引があれば、もう1つ索引を表に作成することの影響を調べたいと思うでしょう。考慮すべき要因には次のものがあります。

  • 変更の影響: DB2はユーザーが作成したすべての索引を自動的に保守します。これは、この表に対するすべてのINSERTおよびDELETEは、表だけでなく索引に対しても挿入、削除を行うことを意味します。そして索引内にある列の値を更新 (UPDATE) すると、索引も更新することになります。したがって索引は参照プロセスを高速化しますが、データの修正を伴う処理は遅くなります。
  • 既存索引中の列: EMPNOかDEPTNOを持つ索引があれば、新たに索引を作成するのは賢いやり方ではありません。むしろ、既存の他の索引に未設定の列を追加する方が、意味があります(必ずしも、そうではない場合もありますが)。それは、照会によっては、索引中の列の順序によって効果が大きく異なるためです。たとえば、次のような照会があるとします。

    SELECT   LASTNAME, SALARY
    FROM     EMP
    WHERE    EMPNO = '000010'
    AND      DEPTNO > 'D01';

    この場合、EMPNOは索引の最初にリストされるべきで、2番目にDEPTNOがリストされるべきです。こうすると、まずDB2は最初の列 (EMPNO) に直接、索引を使った検索を行って絞り込み、次に2番目の列に対して「より大きい」条件でスキャンさせることができるのです。

    さらに、索引が両方の列 (EMPNOとDEPTNOにそれぞれ1つ) にすでに存在する場合、DB2はその両方を使って、この照会の高速検索を行うことができます。したがって、新たに索引を作成する必要はありません。
  • この特定の照会の重要性:照会が重要であればあるほど、索引作成によってチューニングしたいと思うでしょう。会社の最高情報責任者によって毎日実行される照会をコーディングする場合、確実に最高のパフォーマンスが提供されるようにしたいと思うでしょう。したがって、特定の照会用に索引を構築することは重要です。一方、事務職員用の照会に対しては、必ずしもあまり重きを置かず、既存の索引で間に合わせる場合もあるでしょう。もちろんこの意思決定は、ユーザーの重要性だけでなく、ビジネスにとってのアプリケーションの重要性に依存します。

索引設計には、これまで解説したこと以外にも、もっと多くのことが関係します。たとえば、DB2にはインデックス・オンリー・アクセスというテクニックがありますが、これを利用する際には、索引へのデータのつめこみによる過大負荷に注意しなければなりません。たとえば、もしSQLで要求されるすべてのデータが索引内に格納されていれば、DB2はその索引をアクセスするだけで、すべての要求を処理できてしまいます。先ほどのSQL文を例に考えてみましょう。EMPNOとDEPTNOの情報の他、LAST NAMEとSALARYのデータを読み込むとします。そのために、まずEMPNOとDEPTNOの情報をもつ索引を作成します。この索引にLAST NAMEとSALARYのデータも格納しておけば(DB2は索引にデータを格納することもできます)、EMP表へアクセスする必要はなくなります。必要なデータはすべて索引上に存在することになるからです(これが、インデックス・オンリー・アクセスです)。このテクニックにより、I/O処理数が削減できますので、パフォーマンスが大幅によくなります。

すべての照会処理にインデックス・オンリー・アクセスを使うのは賢明なやり方ではありませんし、現実的ではありません。特に問題含みだったり重要なSQLステートメントだけに使用をとどめるべきです。


SQLコーディング・ガイドライン

DB2データをアクセスするSQLステートメントを作成する場合、パフォーマンスを重視したSQLコーディングのための次の3つのガイドラインに必ず従ってください。もちろん、SQLパフォーマンスは複雑なトピックで、SQLがどのように実行されるか完全に理解す至難の技です。とは言え、これら簡単な規則に従えば、パフォーマンスに優れたDB2アプリケーションを開発することが可能です。

  1. 第1の規則は、各SQL SELECTステートメントのSELECTリストには、必要のある列だけ限定して指定することです。言い換えると、「SELECT * を使用してはいけません」。SELECT *は、アクセスする表からすべての列を取り出したい場合に使用します。これは間に合わせの照会には仕方ないにしても、アプリケーション・プログラムには好ましくない手法です。理由は次のとおりです。

    • DB2の表は、将来的に列を追加する変更を必要とするかもしれません。SELECT *はそれら新規列も取り出すので、プログラムはその追加データを処理できるように変更する必要が出てきます。
    • DB2は要求されたすべての列に付加的リソースを消費します。プログラムが必要としないデータは、要求すべきではありません。プログラムがすべての列を必要とする場合でも、SQLステートメント中で各列を名前で明示的に要求する方が明確であり、前項のような落とし穴も回避できて優れています。
  2. すでに知っていることを要求してはいけません。これは当たり前なことのようですが、ほとんどのプログラマーが往々にしてこの規則に違反します。典型的な例として、次のSQLステートメントの何が良くないか考えてみてください。

    SELECT   EMPNO, LASTNAME, SALARY
    FROM     EMP
    WHERE    EMPNO = '000010';

    降参ですか? 問題はEMPNOがSELECTリストに含まれていることです。EMPNOが'000010'と等しいことは、まさにWHERE文節がDB2に指示していることなので、プログラマーはすでに知っています。しかし、WHERE文節にリストされたEMPNOについても、DB2は従順にもその列も取り出します。これで付加的なオーバーヘッドが発生し、パフォーマンスが低下します。
  3. すべてのデータをプログラムに取り込んでフィルターするのではなく、SQLでWHERE文節を使ってデータをフィルターします。前者は初心者によくある過ちです。DB2にとって、プログラムにデータを返す前にデータをフィルターする方が、はるかに優れた手法です。これは、DB2が各データ行を取得するには、付加的なI/OおよびCPUリソースを使用するためです。プログラムに渡す行数が少ないほど、SQLの効率は上がります。

    SELECT  EMPNO, LASTNAME, SALARY
    FROM    EMP
    WHERE   SALARY > 50000.00;

    このWHERE文節を使わずに、単純に全データをプログラム中に取り込んで、そのデータを個々にSALARYが50000.00より大きいかどうかを確かめる方法よりも、このSQLを使用した方法の方が優れています。
  4. パラメーター付き照会を使用します。SQLステートメントにパラメーター、つまり変数を指定する方法です。典型的なパラメーター付き照会は、リテラル値の代わりにこれらパラメーター使用するので、WHERE文節の条件を実行時に変更できます。通常、プログラムは、照会実行前にエンドユーザーがパラメーターの値を指定できるように設計されます。これにより、1つの照会を使用して、パラメーターに指定されたさまざまな値に基づいた異なる結果を戻すことができます。

    パラメーター付き照会の主なパフォーマンス上の利点は、繰り返されるステートメント実行に再利用可能なアクセス・パスを構築できることです。これにより、WHERE文節に新しい値が必要になるたびに完全に新しいSQLステートメントを発行する場合と比べて、プログラムの大幅なパフォーマンス向上が図れます。

しかしながら、これらの規則は、SQLパフォーマンス・チューニングの究極目標ではありません。付加的に徹底的なチューニングが必要になる場合もあります。しかし、上記のような規則に従うことで、アプリケーションのパフォーマンスに致命的な影響を与えるような初心者の間違いをしなくて済みます。


具体的なデータベース・アプリケーション開発のヒント

Delphi、C++Builder、あるいはKylixを使用しているか否かには関らず、DB2データのアクセスで優れたパフォーマンスを保証するうえで、特定の技法やガイドラインが役立ちます。たとえば、ある状況で、ODBC/JDBCやADOの代わりにdbExpress?を使用すると、照会パフォーマンスを改善できます。dbExpressは、Delphi (またはBorland Kylix?) から動的SQLを処理するための、クロスプラットフォーム・インターフェースです。

アプリケーションで頻繁にCOMMITステートメントを発行するようにしてください。COMMITステートメントは作業単位(UOW)をコントロールします。COMMITを発行すると、最後に発行したCOMMITステートメント以降のすべての作業がデータベースに「永久に」記録されます。COMMITを発行する前であれば、ROLLBACKステートメントを使用して作業をロールバックできます。(INSERT、UPDATE、およびDELETEステートメントを使用して) データを変更してもCOMMITを発行しなければ、DB2はそのデータに関するロックを保持します。すると、ロック・データを検索するために待機していた他のアプリケーションが、タイムアウトになることもあります。作業完了時にはCOMMITステートメントを発行してデータが正確に反映されたことを保証することで、他のアプリケーションで使用するためにそのデータを解放します。

また、使い方を念頭にアプリケーションを作成します。たとえば、特定の照会がエンドユーザーに何千行も返す場合には、注意が必要です。エンドユーザーがプログラムに対し、オンラインで対話形式で処理を行うような場合は、仮に数百行を超える答えが返されるのは問題です。SQLステートメントでFETCH FIRST n ROWS ONLY文節を使用すれば、照会に対して返されるデータ量を制限できます。たとえば、次の照会を例にとります。

SELECT  EMPNO, LASTNAME, SALARY
FROM    EMP
WHERE   SALARY > 10000.00
FETCH FIRST 200 ROWS ONLY;

この照会は、200行だけ返します。条件を満たす行が200行を超えていたとしても関係ありません。照会で200行を超えてFETCHを実施しようとすると、DB2は+100 SQLCODEでデータの終わりを知らせます。この方式は、プログラムに返されるデータ量を制限したい場合に便利です。

DB2はOPTIMIZE FOR n ROWSという文節もサポートします。これは、カーソルに返される行数は制限しませんが、パフォーマンスの観点から有益です。OPTIMIZE FOR n ROWS文節は、SQLステートメントの処理方法をDB2に指示するために使用します。例を次に示します。

SELECT   EMPNO, LASTNAME, SALARY
FROM     EMP
WHERE    SALARY > 10000.00
OPTIMIZE FOR 20 ROWS;

このステートメントは、最初の20行を最短で取り出すようにDB2に指示します。これは、たとえばDelphiアプリケーションがデータベースから取り出した行を20行ずつ表示する場合に便利です。

読み取り専用カーソルについては、FOR READ ONLY文節を使用してカーソルの曖昧さを排除します。DelphiではDB2カーソル内での更新は使用できないので、各SELECTステートメントにFOR READ ONLYを追加すれば、カーソルは曖昧さのない読み取り専用カーソルになり、DB2の処理に役立ちます。例を次に示します。

SELECT   EMPNO, LASTNAME, SALARY
FROM     EMP
WHERE    SALARY  > 10000.00
FOR READ ONLY;

まとめ

パフォーマンスを重視したSQLコーディングの基礎を理解すると、Delphiエンタープライズ・アプリケーションは即座にパフォーマンスが飛躍的に向上します。しかし、この文書では氷山の一角とも言えるヒントを示したに過ぎません。結合、副選択、UNIONなどを含め、ますます複雑化するSQLタイプについて、習熟する必要があります。また、これらSQLステートメントの最良の記述方法や、SQL要求を満たすためにDB2が選択したアクセス・パスを検出する方法も習得する必要があります。実際、習得すべきことはまだまだ沢山あります。しかし、DB2 SQLを最大限に活用する方法に着手したということは確かです。

参考文献

DB2 SQLのためのWebリソース

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Information Management
ArticleID=326541
ArticleTitle=パフォーマンス重視のDB2 SQLコーディング:基礎
publish-date=102002