この章では、TimesTen ScaleoutでSQLを使用してデータベースを操作する方法について説明します。内容は次のとおりです。
データベースは、複数の要素で構成されます。各要素にはデータの一部が格納されます。任意の要素からSQL操作を介してデータベース内のデータを操作および問い合せます。たとえば、CREATE USER文を使用して、任意の要素からデータベース内にユーザーを作成できます。TimesTen Scaleoutによってユーザーが作成された後、データベースのすべての要素でこのユーザーを使用できます。任意の要素からDDL文およびDML文を発行し、TimesTen Scaleoutでデータベースのすべての要素に適用できます。SELECT文を発行し、ある要素から作成して別の要素で実行し、結果は元の要素に返されるという問合せを実行できます。
|
ノート:
|
アプリケーションでは、PL/SQLを使用して、データにアクセスして操作できます。無名ブロックは完全にサポートされています。PL/SQLは、アプリケーションが接続されている要素で実行されます。PL/SQLから起動されるSQL文は、他のSQLと同様、グリッド全体で実行されます。
PL/SQLの詳細は、Oracle TimesTen In-Memory Database PL/SQL開発者ガイドを参照し、例については、Oracle TimesTen In-Memory Database PL/SQL開発者ガイドのPL/SQLでのTimesTen SQLの使用例の章を参照してください。サポートされていないPL/SQL機能は、表1-9「TimesTen ScaleoutでサポートされていないTimesTen Classic機能」を参照してください。
表は、データベースのデータを分散する方法を定義するために使用するオブジェクトです。各ユーザー定義表には、定義された分散スキームが含まれています。TimesTen Scaleoutは、この定義された分散スキームに従ってデータの分散を管理します。分散スキームによって、表のデータ行をグリッドで分散する方法 が定義されます。CREATE TABLE文を使用すると、表の分散スキームを定義する分散句を指定できます。作成した表は、データベースのすべての要素に存在します。表のデータ行は、データベースの様々な要素に存在します。
表の作成、変更および削除の構文とセマンティクスの詳細は、Oracle TimesTen In-Memory Database SQLリファレンスのCREATE TABLEを参照してください。分散スキームの定義の詳細は、データ分散または表の分散スキームの定義を参照してください。
TimesTen Scaleoutで表を変更し、デフォルトを変更したり、列および制約を追加および削除することができます。ただし、表が空である場合を除き、分散スキームは変更できません。また、DISTRIBUTE BY REFERENCE句に指定されている制約は削除できません。詳細は、Oracle TimesTen In-Memory Database SQLリファレンスのALTER TABLEを参照してください。
表7-1「分散スキームのALTER TABLEのルール」は、表の変更に関連付けられているルールを示しています。サポートされている例を次に示します。
表7-1 分散スキームのALTER TABLEのルール
| ALTER文 | コメント |
|---|---|
CREATE TABLE t1 (c1 NUMBER, c2 VARCHAR2 (10)); ALTER TABLE t1 DISTRIBUTE BY HASH (c1); |
表が空の場合は、操作は成功します。表が空でない場合、空でない表では分散キーを変更できないため、操作は失敗します。 |
CREATE TABLE t1...CONSTRAINT fk1... DISTRIBUTE BY REFERENCE(fk1); ALTER TABLE t1 DROP CONSTRAINT(fk1); |
操作は失敗します。外部キーは、表を分散するために使用されます。 |
次の例があります。
例7-1 ALTER TABLEを使用した主キー制約の追加
この例では、主キーまたは分散句を使用せずにmytable表を作成します。表は、非表示列のハッシュによって分散されます。次に、ALTER TABLE文を使用して、主キー制約を追加します。操作は成功しますが、分散キーは変更されません。
Command> CREATE TABLE mytable (col1 NUMBER NOT NULL, col2 VARCHAR2 (32));
Command> describe mytable;
Table SAMPLEUSER.MYTABLE:
Columns:
COL1 NUMBER NOT NULL
COL2 VARCHAR2 (32) INLINE
DISTRIBUTE BY HASH
1 table found.
(primary key columns are indicated with *)
これで、表を変更して主キーを追加します。操作は成功します。分散スキームおよび分散キーは変更されません。
Command> ALTER TABLE mytable ADD CONSTRAINT c1 PRIMARY KEY (col1);
Command> describe mytable;
Table SAMPLEUSER.MYTABLE:
Columns:
*COL1 NUMBER NOT NULL
COL2 VARCHAR2 (32) INLINE
DISTRIBUTE BY HASH
1 table found.
(primary key columns are indicated with *)
例7-2 ALTER TABLEを使用した分散キーの変更
この例では、ALTER TABLE文を使用して分散キーを変更できることを示します(ただし、表が空の場合のみ)。
Command> CREATE TABLE mytable2 (col1 NUMBER NOT NULL, col2 VARCHAR2 (32)) DISTRIBUTE BY HASH (col1,col2);
Command> describe mytable2;
Table SAMPLEUSER.MYTABLE2:
Columns:
COL1 NUMBER NOT NULL
COL2 VARCHAR2 (32) INLINE
DISTRIBUTE BY HASH (COL1, COL2)
1 table found.
(primary key columns are indicated with *)
ALTER TABLE文を使用して、分散キーをcol1に変更します。表が空のため、操作は成功します。
Command> ALTER TABLE mytable2 DISTRIBUTE BY HASH (col1);
Command> describe mytable2;
Table SAMPLEUSER.MYTABLE2:
Columns:
COL1 NUMBER NOT NULL
COL2 VARCHAR2 (32) INLINE
DISTRIBUTE BY HASH (COL1)
1 table found.
(primary key columns are indicated with *)
マテリアライズド・ビューは、データの行を分散するための2つ目の方法です。(1つ目の方法は表です。)詳細は、分散のセカンダリ・フォームとしてのマテリアライズド・ビューを参照してください。
マテリアライズド・ビューは、複数要素へのアクセス(ブロードキャスト)を低減または排除するグローバル索引として役立ちます。詳細は、索引の理解を参照してください。
その他の考慮事項:
DISTRIBUTE BY HASH分散スキームを指定します。DISTRIBUTE BY REFERENCE句およびDUPLICATE句はサポートされていません。
DISTRIBUTE BY HASH句を指定し、DISTRIBUTE BY句に列セットを指定する必要があります。主キーでマテリアライズド・ビューを分散する場合でも、分散句に主キーを指定する必要があります。
ディテール表に一意の列があり、かつ一意の列がマテリアライズド・ビューの分散キーとして使用される場合は、マテリアライズド・ビューの一意索引を作成します。その列がDML操作および問合せで頻繁に使用される場合は、このことによってパフォーマンスが向上します。
一意索引列および主キー列は、分散キー列のスーパー・セットである必要があります。
表への移入にかかる時間を短縮するために、表への移入の後に表のマテリアライズド・ビューおよび索引を作成することを検討してください。
マテリアライズド・ビューの詳細は、Oracle TimesTen In-Memory Database SQLリファレンスのCREATE MATERIALIZED VIEWを参照してください。
索引を作成すると、TimesTen Scaleoutによって、分散マップ内のすべての要素の索引が作成されます。TimesTen Scaleoutは、各要素の索引に、その要素に格納されている行を移入します。索引を削除すると、TimesTen Scaleoutによってすべての要素の索引が削除されます。
分散キーのすべての列が含まれていない索引アクセスでは、複数要素へのアクセス(すべての要素にわたるブロードキャスト)が必要になります。ブロードキャストを回避して索引アクセスを最適化するために、マテリアライズド・ビューおよびマテリアライズド・ビューに対する索引を作成することを検討してください。例7-3「グローバル索引としてのマテリアライズド・ビューの使用」は、マテリアライズド・ビューを作成して索引アクセスを最適化する方法を示しています。
|
ノート: マテリアライズド・ビューに定義されている列に対するDML操作では、記憶域およびオーバーヘッド・コストが必要になります。これは、TimesTen Scaleoutでのキー・チューニングのトレードオフです。 |
例7-3 グローバル索引としてのマテリアライズド・ビューの使用
accounts表は、cust_idに基づいた参照によって分散されます。分散キーが使用されていないUPDATE文のパフォーマンスを向上させるには、マテリアライズド・ビューを作成することを検討し、分散キー(この例ではaccount_id)に含まれていない列にマテリアライズド・ビューを分散します。次に、account_id列の索引を作成します。ttIsql set timingコマンドを使用して、実行時間の違いを示します。
ttIsql describeコマンドを使用して、accounts表を説明します。
Command> SELECT status FROM accounts WHERE account_id = 500;
< 10 >
1 row found.
Command> autocommit off;
Command> set timing on;
Command> UPDATE accounts SET status=20 WHERE account_id=500;
1 row updated.
Execution time (SQLExecute) = 1.018369 seconds.
Command> set timing off;
Command> SELECT status FROM accounts WHERE account_id = 500;
< 20 >
1 row found.
Command> rollback;
Command> SELECT status FROM accounts WHERE account_id = 500;
< 10 >
1 row found.
Command> CREATE MATERIALIZED VIEW account_id_mv
DISTRIBUTE BY HASH (account_id) AS SELECT * FROM accounts;
1010000 rows materialized.
Command> CREATE UNIQUE HASH INDEX account_index_mv ON account_id_mv (account_id);
Command> autocommit off;
Command> set timing on;
Command> UPDATE accounts SET status=20 WHERE account_id=500;
1 row updated.
Execution time (SQLExecute) = 0.002601 seconds.
Command> set timing off;
Command> rollback;
Command> SELECT status FROM accounts WHERE account_id = 500;
< 10 >
1 row found.
複数のユーザーが一意のBIGINTデータ型を生成するために使用できる新しい順序番号ジェネレータが、CREATE SEQUENCE文によって作成されます。マテリアライズド・ビューおよび表と同様、順序オブジェクトを作成すると、データベースの任意の要素から順序値を取得できます。
値が取得されるたびに順序オブジェクトでグローバルに調整された更新を実行するオーバーヘッドを削減するために、値は順序からブロックで取得され、キャッシュされます。TimesTen Scaleoutで順序から返される値は一意であることが保証されている一方で、連続していることは保証されていません。
BATCH句は、TimesTen Scaleoutに固有のものです。バッチ値によって、要素に格納された一意の順序値の範囲が構成されます。各要素にはその独自のバッチがあります。要素のローカル・バッチが消費されると、要素は新しいバッチを取得します。順序を所有し、バッチ順序ブロックを他の要素に割り当てる責任を担う要素が1つあります。
順序値は一意ですが、この値は要素をまたいで単調な順番では返されない可能性があります。1つの要素内では、順序値の順番は単調です。ただし、時間の経過に伴い、要素をまたいでは順序値は単調に返されません。ただし、単調なプロパティは、1つの要素内では保証されます。
アプリケーションがイベントを記録し、順序値で各イベントにタグ付けする場合、たとえば、アプリケーションではイベント100がイベント80の後に発生することを想定できません。アプリケーションでこのように想定する必要がある場合は、BATCHを1に設定します。ただし、BATCHを1に設定すると、かなりの通信のオーバーヘッドが発生します。
つまり、BATCH値が1に設定されていない場合、順序値の順番がすべての要素をまたいで維持されることは保証されません。ただし、バッチ値が何であっても、順序値の一意性がすべての要素をまたいで維持されることは保証されます。また、順序値の順番が1つの要素内で維持されることは保証されます。
既存の順序のデフォルトのバッチ値を変更するには、ALTER SEQUENCE文を発行します。バッチ値は、変更可能な唯一の句です。詳細は、Oracle TimesTen In-Memory Database SQLリファレンスのCREATE SEQUENCEおよびALTER SEQUENCEを参照してください。順序を削除するには、DROP SEQUENCE文を使用します。順序の削除の詳細は、Oracle TimesTen In-Memory Database SQLリファレンスののDROP SEQUENCEを参照してください。
バッチ値に何を設定するかは、次の考慮事項によって異なります。
値を1に設定すると、存在する要素の数に関係なく、順序値は単調な順番で発行されます。ただし、値が1の場合は、かなりの通信のオーバーヘッドが発生し、パフォーマンスに悪影響を与えます。システムのパフォーマンスに直接影響するため、必要な場合以外は、値を1に設定しないでください。
1より大きい値を設定すると、一意の順序値はすべての要素をまたいで厳密な順番で発行されません。接続が順序から複数の値を取得する場合、これらの値が切れ目なく連続する保証はありません。複数の接続が順序から値を取得する場合、取得される値の範囲にギャップが存在する可能性があります。
要素間の過度の通信を回避するために、バッチを大きい値に設定することを検討する必要があります(アプリケーションが適切に機能するためにバッチ値を1に設定する必要がある場合を除く)。
バッチ境界内の一意の順序値は、MAXVALUEより大きくすることはできません。たとえば、順序が1ずつ増分し、バッチ値が3、最大値が5の場合、最初のバッチには1、2、3が含まれています。2番目のバッチには4および5のみが含まれています。
バッチ値は、キャッシュ値以上である必要があります。
バッチ値を指定しない場合、デフォルトは1000万です。各要素には、最初は、独自の1000万件の値があります。1000万の値を使い果たすと、要素はさらに1000万件を取得します。最小値と最大値および一意の値の数は、MINVALUE、MAXVALUEおよびINCREMENT BYの値によって決定されます。
レプリカ・セットの各要素には、様々なバッチがあります。
バッチ割当ての例を次に示します。
例7-4 3つの要素に対するバッチ割当ての説明
この例では、myseq順序を作成し、バッチ値を100とします。次に、要素1に接続されている接続から、SELECT...NEXTVAL問合せを発行します。この例では、要素2に接続されている接続および要素3に接続されている接続から、それぞれ2番目および3番目のSELECT...NEXTVAL問合せを発行します。この例は、各要素に対するバッチ割当ての割当てを示しています。この例の詳細は次のとおりです。
要素1は1-100のバッチを受信します。
要素2は101-200のバッチを受信します。
要素3は201-300のバッチを受信します。
要素1に接続されている接続から(SELECT elementId# FROM dualで示されている)、バッチ値100を指定してmyseq順序を作成します。次に、SELECT...NEXTVAL問合せを発行します。値1が返されることを確認します。
Command> SELECT elementId# FROM dual; < 1 > 1 row found. Command> CREATE SEQUENCE myseq BATCH 100; Command> SELECT myseq.NEXTVAL FROM dual; < 1 > 1 row found.
要素2に接続されている接続から、最初に要素2への接続を確認し、次にSELECT...NEXTVAL問合せを発行します。値101が返されることを確認します。
Command> SELECT elementId# FROM dual; < 2 > 1 row found. Command> SELECT myseq.NEXTVAL FROM dual; < 101 > 1 row found.
要素3に接続されている接続から、最初に要素3への接続を確認し、次にSELECT...NEXTVAL問合せを発行します。値201が返されることを確認します。
Command> SELECT elementId# FROM dual; < 3 > 1 row found. Command> SELECT myseq.NEXTVAL FROM dual; < 201 > 1 row found.
例7-5 3つの要素に対する2番目のバッチ割当ての説明
この例では、バッチ値が100のmyseq2順序を作成します。次に、要素1に接続されている接続から、SELECT...NEXTVAL問合せを発行します。この例では、要素3に接続されている接続および要素2に接続されている接続から、それぞれ2番目および3番目のSELECT...NEXTVAL問合せを発行します。この例は、各要素に対するバッチ割当ての割当てを示しています。この例の詳細は次のとおりです。
要素1は1-100のバッチを受信します。
要素3は101-200のバッチを受信します。
要素2は201-300のバッチを受信します。
要素1に接続されている接続から(SELECT elementId# FROM dualで示されている)、バッチ値100を指定してmyseq2順序を作成します。次に、SELECT...NEXTVAL問合せを発行します。値1が返されることを確認します。
Command> SELECT elementId# FROM dual; < 1 > 1 row found. Command> CREATE SEQUENCE myseq2 BATCH 100; Command> SELECT myseq2.NEXTVAL FROM dual; < 1 > 1 row found.
要素3に接続されている接続から、最初に要素3への接続を確認し、次にSELECT...NEXTVAL問合せを発行します。値101が返されることを確認します。
Command> SELECT elementId# FROM dual; < 3 > 1 row found. Command> SELECT myseq2.NEXTVAL FROM dual; < 101 > 1 row found.
要素2に接続されている接続から、最初に要素2への接続を確認し、次にSELECT...NEXTVAL問合せを発行します。値201が返されることを確認します。
Command> SELECT elementId# FROM dual; < 2 > 1 row found. Command> SELECT myseq2.NEXTVAL FROM dual; < 201 > 1 row found.
TimesTen Scaleoutでは、INSERT、DELETE、UPDATE、SELECT DML操作がサポートされています。MERGE操作はサポートされていません。
すべての要素内のすべてのデータに、どこからでもアクセスできます。任意の要素またはすべての要素内のデータを問い合せたり、変更することができます。トランザクションはACIDルールに従います。TimesTen Scaleoutは、分離レベルのコミット読取りセマンティクスを提供します。リーダーはライターをブロックせず、ライターはリーダーをブロックしません。
疑似列は、列と同じコンテキストで使用される割当て値ですが、格納されていません。疑似列は、表の実際の列ではありませんが、列と同じように動作します。疑似列では、選択操作を実行できますが、挿入、更新または削除操作は実行できません。
replicaSetId#疑似列を使用して、行が格納されているレプリカ・セットを判断します。この疑似列は、NOT NULL TT_INTEGERデータ型を返します。
TimesTen Scaleoutでサポートされているその他の疑似列の詳細は、Oracle TimesTen In-Memory Database SQLリファレンスのTimesTen Scaleoutの疑似列を参照してください。
次の例があります。
例7-6 replicaSetId#を使用したデータの検索
この例では、customers表に対する問合せを発行し、データが格納されているレプリカ・セットを返します(replicaSetId#により決定される)。
Command> SELECT replicasetid#, cust_id,last_name,first_name
FROM customers WHERE cust_id BETWEEN 910 AND 920
ORDER BY cust_id, last_name, first_name;
< 2, 910, Riley, Tessa >
< 1, 911, Riley, Rashad >
< 1, 912, Riley, Emma >
< 1, 913, Rivera, Erin >
< 1, 914, Roberts, Ava >
< 1, 915, Roberts, Lee >
< 2, 916, Roberts, Clint >
< 3, 917, Robertson, Faith >
< 2, 918, Robinson, Miguel >
< 2, 919, Robinson, Mozell >
< 3, 920, Rodgers, Darryl >
11 rows found.
例7-7 複製分散スキームの表でのreplicaSetId#の使用
この例では、最初にaccount_status表でttIsql describeコマンドを使用して、表が複製分散スキームであるかどうかを確認します。次に、replicasetId#を返す問合せを発行します。次に、別の接続から同じ問合せを繰り返します。この例は、返されるデータが、アプリケーションが接続されているレプリカ・セットに配置され、データベースのすべての要素に存在することを示しています(複製分散スキーム)。
Command> describe account_status;
Table SAMPLEUSER.ACCOUNT_STATUS:
Columns:
*STATUS NUMBER (2) NOT NULL
DESCRIPTION VARCHAR2 (100) INLINE NOT NULL
DUPLICATE
1 table found.
(primary key columns are indicated with *)
dual表を問い合せて、アプリケーションが接続されているレプリカ・セットを返します。この例では、レプリカ・セットは1です。
Command> SELECT replicaSetId# FROM dual; < 1 > 1 row found. Command> SELECT replicaSetId#,* FROM account_status; < 1, 10, Active - Account is in good standing > < 1, 20, Pending - Payment is being processed > < 1, 30, Grace - Automatic payment did not process successfully > < 1, 40, Suspend - Account is in process of being disconnected > < 1, 50, Disconnected - You can no longer make calls or receive calls > 5 rows found.
別のデータ・インスタンスで実行されている別のttIsqlセッションから2番目の問合せを発行します。
Command> SELECT elementid# from dual; < 6> 1 row found. Command> SELECT replicaSetId#, * FROM account_status; < 3, 10, Active - Account is in good standing > < 3, 20, Pending - Payment is being processed > < 3, 30, Grace - Automatic payment did not process successfully > < 3, 40, Suspend - Account is in process of being disconnected > < 3, 50, Disconnected - You can no longer make calls or receive calls > 5 rows found.
TT_CommitDMLOnSuccessヒントは、コミット操作をDML実行の一部として有効または無効にするために使用されます。このヒントは、接続レベルまたは文レベルで指定できます。
このヒントを使用中(TT_CommitDMLOnSuccessが1に設定されている場合)は、次のようになります。
文レベルでは、実行中に文でエラーが発生した場合、トランザクションはアクティブなままで、データベースの一貫性が保たれます。
単一のレプリカ・セットに影響を与えるトランザクションの場合、コミット操作では2フェーズ・コミット・プロトコルではなく1フェーズ・コミットを使用します。
autocommitを1に設定した場合や、TT_CommitDMLOnSuccessヒントを1に設定した場合は、パフォーマンスに違いはありません。
詳細は、『Oracle TimesTen In-Memory Database SQLリファレンス』のTT_CommitDMLOnSuccessオプティマイザ・ヒントに関する項を参照してください。
TimesTen問合せオプティマイザはコストベースのオプティマイザで、使用可能な問合せ計画を検討することにより、指定された問合せを実行する最も効率的な方法を決定します。TimesTen Scaleoutの問合せ計画は、ハッシュ分散スキームの分散スキームおよび分散キー、列および表の統計、索引の有無、データ量、一意の値の数、述語の選択性の影響を受けます。問合せ計画を手動で調べるには、ttIsql explainコマンドを実行します。詳細は、Oracle TimesTen In-Memory Databaseオペレーション・ガイドのTimesTen問合せオプティマイザを参照してください。
オプティマイザ・ヒントを使用して、オプティマイザによって生成された実行計画に影響を与えることができます。TimesTen Scaleoutに固有のオプティマイザ・ヒントは2つあります。これらのヒントは、文レベルおよび接続レベルで有効です。文レベルでは、ヒントは、SELECT文に対してのみ有効です。
TimesTen Scaleoutに固有のオプティマイザ・ヒントの詳細は、『Oracle TimesTen In-Memory Database SQLリファレンス』のTimesTen Scaleoutのみでサポートされているオプティマイザ・ヒントに関する項を参照してください。すべてのオプティマイザ・ヒントの詳細は、Oracle TimesTen In-Memory Databaseオペレーション・ガイドのオプティマイザ・ヒントを使用して実行計画を変更するを参照してください。
TT_GridQueryExecオプティマイザ・ヒントを使用すると、問合せによって、ローカル要素から、またはすべての要素から(K-safetyが2に設定されている場合はレプリカ・セット内の要素を含む)のデータが返されるようにすることを指定できます。
このヒントを指定しない場合、問合せは1つの論理データ領域で実行されます。これはローカルでもグローバルでもありません。データの1つの完全コピーを使用して、問合せを計算します。
このヒントの有効なオプションは、LOCALおよびGLOBALです。
LOCAL: TimesTen Scaleoutは、ローカル要素でのみ問合せを実行します。データは、接続先の要素からローカルに取得されます。ローカル要素がデータの完全コピーを持っていない場合、TimesTen Scaleoutは結果の一部を返します。
GLOBAL: TimesTen Scaleoutはすべての要素からデータを取得します(結果を生成するすべてのレプリカ・セットのすべての表の行のコピーを含む)。K-safetyが2に設定されている場合、または表が複製分散スキームである場合は、重複したデータが返されます。
すべての問合せと同様に、直接接続して、SQL問合せを発行する要素は、問合せを作成してこれをグリッド内の他のすべての要素に送信します。リクエストは稼働中の要素で実行され、結果は接続している要素にローカルにレポートされます。
このヒントの構文とセマンティクスの詳細は、Oracle TimesTen In-Memory Database SQLリファレンスのTT_GridQueryExecオプティマイザ・ヒントを参照してください。
分散スキームは、返される行数の決定ファクタです。たとえば、表7-2は、3つの分散スキームでの問合せで使用される行数を示しています。kはコピーの数を表し(例ではk=2)、eは各レプリカ・セットの1つの要素を表し(例ではe=3)、rは表内の行数を表します。
表7-2 TT_GridQueryExecオプティマイザ・ヒント
| オプション | 表タイプ | 問合せで使用される行数 |
|---|---|---|
|
|
複製分散スキーム表 ハッシュ表で分散 参照表で分散 |
r r/e 均一な分散を想定 r/e 均一な分散を想定 |
|
|
複製分散スキーム表 ハッシュ表で分散 参照表で分散 |
e*k*r k*r k*r |
次の例があります。
|
ノート: 読取りでは、分散ロックは取得されず、コミット済データが返されます。TT_GridQueryExec(GLOBAL)オプティマイザ・ヒントを使用する例の場合、レプリカ・セットへの書込みがレプリカへの読取り間で行われる場合、その数がすべてのレプリカで一致しない可能性があります。各レプリカにはコミット読取りの分離が許可されているため、これは予想される動作です。 |
例7-8 ハッシュ分散スキーム表でのTT_GridQueryExecの使用
この例では、customers表でttIsql describeコマンドを使用して、表がハッシュで分散されていることを示します。この例では、customers表でSELECT COUNT (*)問合せを実行して、表の行数(1000)を返します。要素4に接続されている接続から、この例ではTT_GridQueryExec (Local)および(Global)オプティマイザ・ヒントを使用して行数を返します。返される行は、TT_GridQueryExecヒントにLocalとGlobalのどちらが指定されたかに基づいて異なります。
Command> describe customers;
Table SAMPLEUSER.CUSTOMERS:
Columns:
*CUST_ID NUMBER (10) NOT NULL
FIRST_NAME VARCHAR2 (30) INLINE NOT NULL
LAST_NAME VARCHAR2 (30) INLINE NOT NULL
ADDR1 VARCHAR2 (64) INLINE
ADDR2 VARCHAR2 (64) INLINE
ZIPCODE VARCHAR2 (5) INLINE
MEMBER_SINCE DATE NOT NULL
DISTRIBUTE BY HASH (CUST_ID)
1 table found.
(primary key columns are indicated with *)
Command> SELECT COUNT (*) FROM customers;
< 1000 >
1 row found.
SELECT elementId# FROM dual問合せを発行して、ローカル要素接続(4)を決定します。
Command> SELECT elementId# FROM dual; < 4 > 1 row found.
この接続から、TT_GridQueryExec(LOCAL)オプティマイザ・ヒントを指定するSELECT問合せを発行します。約333行が返されると予想されます(1000/3)。
Command> SELECT /*+TT_GridQueryExec(LOCAL)*/ COUNT (*), elementId#
FROM customers GROUP BY elementId#;
< 326, 4 >
1 row found.
ここで、TT_GridQueryExec(GLOBAL)オプティマイザ・ヒントを指定するSELECT問合せを発行します。2000行が返されると予想されます(k=2 * r=1000 = 2000)。結果を確認するには、SUM関数を使用して、6要素すべてに対して返された行の合計を計算します。
Command> SELECT /*+TT_GridQueryExec(GLOBAL)*/ COUNT (*), elementId#
FROM customers GROUP BY elementId#
ORDER BY elementId#;
< 338, 1 >
< 338, 2 >
< 326, 3 >
< 326, 4 >
< 336, 5 >
< 336, 6 >
6 rows found.
Command> SELECT SUM (338+338+326+326+336+336) FROM dual;
< 2000 >
1 row found.
合計数を確認するには、TT_GridQueryExec(GLOBAL)ヒントを使用します。
Command> SELECT/*+TT_GridQueryExec(GLOBAL)*/ COUNT(*) FROM customers; < 2000 > 1 row found.
例7-9 複製分散スキーム表でのTT_GridQueryExecの使用
この例では、account_status表でttIsql describeコマンドを使用して、表が複製分散スキームであるかどうかを示します。この例では、account_status表でSELECT COUNT (*)問合せを実行して、表の行数(5)を返します。要素2に接続されている接続から、この例ではTT_GridQueryExec (Local)および(Global)オプティマイザ・ヒントを使用して行数を返します。返される行は、TT_GridQueryExecヒントにLocalとGlobalのどちらが指定されたかに基づいて異なります。
Command> describe account_status;
Table SAMPLEUSER.ACCOUNT_STATUS:
Columns:
*STATUS NUMBER (2) NOT NULL
DESCRIPTION VARCHAR2 (100) INLINE NOT NULL
DUPLICATE
1 table found.
(primary key columns are indicated with *)
Command> SELECT count (*) FROM account_status;
< 5 >
1 row found.
Command> SELECT elementId# FROM dual;
< 2 >
1 row found.
TT_GridQueryExec(LOCAL)オプティマイザ・ヒントを指定するSELECT問合せを発行します。約5行が返されると予想されます(r = 5)。
Command> SELECT /*+TT_GridQueryExec(LOCAL)*/ COUNT (*),elementId#
FROM account_status GROUP BY elementId#;
< 5, 2 >
1 row found.
ここで、TT_GridQueryExec(GLOBAL)オプティマイザ・ヒントを指定するSELECT問合せを発行します。30行が返されると予想されます(e=3 *k=2 * r=5= 30)。
Command> SELECT /*+TT_GridQueryExec(GLOBAL)*/ COUNT (*),elementId#
FROM account_status GROUP BY elementId#
ORDER BY elementId#;
< 5, 1 >
< 5, 2 >
< 5, 3 >
< 5, 4 >
< 5, 5 >
< 5, 6 >
6 rows found.
合計数を確認するには、TT_GridQueryExec(GLOBAL)ヒントを使用します。
Command> SELECT /*+TT_GridQueryExec(GLOBAL)*/ COUNT (*) FROM account_status; < 30 > 1 row found.
例7-10 参照分散スキーム表でのTT_GridQueryExecの使用
この例では、accounts表でttIsql describeコマンドを使用して、表が参照で分散されていることを示します。この例では、accounts表でSELECT COUNT (*)問合せを実行して、表の行数(1010)を返します。要素1に接続されている接続から、この例ではTT_GridQueryExec (Local)および(Global)オプティマイザ・ヒントを使用して行数を返します。返される行は、TT_GridQueryExecヒントにLocalとGlobalのどちらが指定されたかに基づいて異なります。
Command> describe accounts;
Table SAMPLEUSER.ACCOUNTS:
Columns:
*ACCOUNT_ID NUMBER (10) NOT NULL
PHONE VARCHAR2 (15) INLINE NOT NULL
ACCOUNT_TYPE CHAR (1) NOT NULL
STATUS NUMBER (2) NOT NULL
CURRENT_BALANCE NUMBER (10,2) NOT NULL
PREV_BALANCE NUMBER (10,2) NOT NULL
DATE_CREATED DATE NOT NULL
CUST_ID NUMBER (10) NOT NULL
DISTRIBUTE BY REFERENCE (FK_CUSTOMER)
1 table found.
(primary key columns are indicated with *)
Command> SELECT COUNT (*) FROM accounts;
< 1010 >
1 row found.
Command> SELECT elementId# FROM dual;
< 1 >
1 row found.
TT_GridQueryExec(LOCAL)オプティマイザ・ヒントを指定するSELECT問合せを発行します。約336行が返されると予想されます(1010/3)。
Command> SELECT /*+TT_GridQueryExec(LOCAL)*/ COUNT (*), elementId#
FROM accounts GROUP BY elementId#;
< 339, 1>
1 row found.
ここで、TT_GridQueryExec(GLOBAL)オプティマイザ・ヒントを指定するSELECT問合せを発行します。2020行が返されると予想されます(k=2 * r=1010 = 2020)。結果を確認するには、SUM関数を使用して、6要素すべてに対して返された行の合計を計算します。
Command> SELECT /*+TT_GridQueryExec(GLOBAL)*/ COUNT (*), elementId#
FROM accounts GROUP BY elementId#
ORDER BY elementId#;
< 339, 1 >
< 339, 2 >
< 332, 3 >
< 332, 4 >
< 339, 5 >
< 339, 6 >
6 rows found.
Command> SELECT SUM (339+339+332+332+339+339) FROM dual;
< 2020 >
1 row found.
合計数を確認するには、TT_GridQueryExec(GLOBAL)ヒントを使用します。
Command> SELECT/*+TT_GridQueryExec(GLOBAL)*/ COUNT(*) FROM accounts; < 2020 > 1 row found.
TT_PartialResultオプティマイザ・ヒントを使用すると、データを使用できない場合に、問合せによって結果の一部が返されるようにするか、エラーが返されるようにするかを指定できます。
レプリカ・セット内のすべての要素を使用できない場合に、問合せによって結果の一部が返されるようにするには、TT_PartialResult(1)を使用します。
レプリカ・セット内のすべての要素を使用できず、必要なデータを使用できない場合に、問合せによってエラーが返されるようにするには、TT_PartialResult(0)を使用します。各レプリカ・セットの少なくとも1つの要素が使用可能であるか、問合せに必要なデータが使用可能な場合、オプティマイザは問合せ結果を正常に返し、エラーは発生しません。
デフォルトはTT_PartialResult(0)です。
このヒントの構文とセマンティクスの詳細は、Oracle TimesTen In-Memory Database SQLリファレンスのTT_PartialResultオプティマイザ・ヒントを参照してください。
例7-11 TT_PartialResultを使用した結果の調査
この例では、elementId#、replicaSetId#およびdataspaceId#疑似列を選択して、問合せに含まれるデータ行を探します。要素3および4を使用できないようにします。TT_PartialResultを0に設定すると、レプリカ・セットを使用できない場合はエラーが返されます。TT_PartialResultを1に設定すると、使用可能な要素から結果の一部が返されます。
Command> SELECT elementId#,replicasetId#,dataspaceId#, last_name,first_name
FROM customers WHERE last_name LIKE ('%Wh%') ORDER BY last_name;
< 6, 3, 2, Whitaker, Armand >
< 4, 2, 2, Whitaker, Ariel >
< 6, 3, 2, White, Carlene >
< 6, 3, 2, White, Marcelo >
< 4, 2, 2, White, Dona >
< 4, 2, 2, White, Ellyn >
< 4, 2, 2, White, Nora >
< 4, 2, 2, White, Phylis >
8 rows found.
Command> SELECT /*+TT_PartialResult(0)*/ elementId#,replicasetId#,dataspaceId#,
last_name,first_name FROM customers
WHERE last_name like ('%Wh%') ORDER BY last_name;
< 6, 3, 2, Whitaker, Armand >
< 4, 2, 2, Whitaker, Ariel >
< 6, 3, 2, White, Carlene >
< 6, 3, 2, White, Marcelo >
< 4, 2, 2, White, Dona >
< 4, 2, 2, White, Ellyn >
< 4, 2, 2, White, Nora >
< 4, 2, 2, White, Phylis >
8 rows found.
Command> SELECT /*+TT_PartialResult(1)*/ elementId#,replicasetId#,dataspaceId#,
last_name,first_name FROM customers
WHERE last_name LIKE ('%Wh%') ORDER BY last_name;
< 6, 3, 2, Whitaker, Armand >
< 4, 2, 2, Whitaker, Ariel >
< 6, 3, 2, White, Carlene >
< 6, 3, 2, White, Marcelo >
< 4, 2, 2, White, Dona >
< 4, 2, 2, White, Ellyn >
< 4, 2, 2, White, Nora >
< 4, 2, 2, White, Phylis >
8 rows found.
要素4は使用できません。同じ結果が予想されます。要素3は使用できます。
Command> SELECT /*+TT_PartialResult(1)*/ elementId#,replicasetId#,dataspaceId#,
last_name,first_name FROM customers
WHERE last_name LIKE ('%Wh%') ORDER BY last_name;
< 6, 3, 2, Whitaker, Armand >
< 3, 2, 1, Whitaker, Ariel >
< 6, 3, 2, White, Carlene >
< 6, 3, 2, White, Marcelo >
< 3, 2, 1, White, Dona >
< 3, 2, 1, White, Ellyn >
< 3, 2, 1, White, Nora >
< 3, 2, 1, White, Phylis >
8 rows found.
Command> SELECT /*+TT_PartialResult(0)*/ elementId#,replicasetId#,dataspaceId#,
last_name,first_name FROM customers
WHERE last_name LIKE ('%Wh%') ORDER BY last_name;
< 6, 3, 2, Whitaker, Armand >
< 3, 2, 1, Whitaker, Ariel >
< 6, 3, 2, White, Carlene >
< 6, 3, 2, White, Marcelo >
< 3, 2, 1, White, Dona >
< 3, 2, 1, White, Ellyn >
< 3, 2, 1, White, Nora >
< 3, 2, 1, White, Phylis >
8 rows found.
これで、要素3は使用できなくなります。レプリカ・セット2は使用できません。TT_PartialResultを1に設定すると、結果の一部が返されると予想されます。TT_PartialResultを0に設定すると、エラーが返されると予想されます。
Command> SELECT /*+TT_PartialResult(1)*/ elementId#,replicasetId#,dataspaceId#,
last_name,first_name FROM customers
WHERE last_name LIKE ('%Wh%') ORDER BY last_name;
< 6, 3, 2, Whitaker, Armand >
< 6, 3, 2, White, Carlene >
< 6, 3, 2, White, Marcelo >
3 rows found.
Command> SELECT /*+TT_PartialResult(0)*/ elementId#,replicasetId#,dataspaceId#,
last_name,first_name FROM customers
WHERE last_name LIKE ('%Wh%') ORDER BY last_name;
3723: Replica set 2 down
The command failed.
TimesTen Scaleoutでは、行分散のために一意のIDが必要になります。すべての要素にわたる一意性を確保するために、ROWIDが使用されます。
K-safetyが1に設定されている複製分散スキームの表、およびK-safetyが2に設定されているすべての表(分散スキームが何であっても関係ありません)の場合、行の各コピーの物理的な場所は異なるため、行の各コピーのROWID値は異なります。この場合、ROWIDベースのアクセスを使用すると、TimesTen Scaleoutは最初のデータ領域のROWIDの値を返します。最初のデータ領域の行を使用できない場合、TimesTen Scaleoutは次(2番目)のデータ領域のROWIDを返します。
ROWIDは行の特定のコピーの識別子であるため、そのコピーを使用できない場合は、ROWIDで行にアクセスできません。この場合は、主キーで行にアクセスする必要があります。
詳細は、Oracle TimesTen In-Memory Database SQLリファレンスのROWID疑似列を参照してください。
|
ノート: アプリケーションは、データベースにROWID値を格納せず、これらの値を後で使用しようとします。アプリケーションはトランザクションでROWIDをフェッチし、後で同じトランザクションでROWIDを使用できます。 |