MR_COUNTERの使用

SQL文を使用して複数リージョン表でMR_COUNTERを作成および管理する方法について学習します。

MR_COUNTERデータ型は、競合のないレプリケートされたデータ型(CRDT)カウンタです。CRDTを使用すると、ユーザーの介入なしで、複数のリージョンにわたり同時変更をマージできます。

Oracle NoSQL Databaseの複数リージョン設定では、同じデータのコピーを複数のリージョンに格納する必要があり、様々なリージョンでデータが同時に変更される場合があります。MR_COUNTERデータ型を使用すると、様々なリージョンで同時にデータ変更が実行されても、データは常に、自動的マージされて一貫性のある状態になります。

現在、Oracle NoSQL Databaseでは、正/負(PN)のMR_COUNTERデータ型のみがサポートされています。PNカウンタは、増分操作と減分操作に適しています。たとえば、これらのカウンタを使用して、任意の時点でWebサイトからサッカーの試合をライブ・ストリーミングしている視聴者の数をカウントできます。視聴者がオフラインになったときに、そのカウンタを減分する必要があります。

MR_COUNTERを定義できるのは、表の作成中または表の変更中のみです。

MR_COUNTERデータ型を使用した表の作成

CREATE TABLE文で、表内のMR_COUNTERデータ型の列を宣言できます。MR_COUNTERは、INTEGER、LONG、NUMBERデータ型のどれかのサブタイプです。
CREATE TABLE Users (
  id integer,
  firstname string,
  lastname string,
  age integer,
  income integer,
  count integer AS MR_COUNTER,
  primary key (id)
) IN REGIONS FRA,LON; 

MR_COUNTERデータ型は、複数リージョン表の場合のみ使用できます。通常の表では使用できません。前述の文では、FRAリージョンとLONリージョンに複数リージョン表を作成して、countをINTEGER MR_COUNTERデータ型として含めています。複数リージョン表では、複数の列をMR_COUNTERデータ型として定義できます。

JSONドキュメント内のフィールドをMR_COUNTERとして宣言することもできます。
CREATE TABLE IF NOT EXISTS JSONPersons (
  id integer,
  person JSON (counter as INTEGER MR_COUNTER,
               books.count as LONG MR_COUNTER),
  primary key (id)
) IN REGIONS FRA,LON;

前述の文では、JSONドキュメントperson内の2つのフィールドをMR_COUNTERとして指定しています。最初のフィールドcounterは、INTEGER MR_COUNTERデータ型です。2番目のフィールドcountは、ネストされたJSONドキュメントbooks内にあります。このcountフィールドはLONG MR_COUNTERデータ型です。

複数リージョン表への行の挿入

INSERT文を使用して、MR_COUNTER列を含む複数リージョン表にデータを挿入できます。次のオプションのどれかを使用して行を追加できます。どちらのオプションでも、MR_COUNTER列にデフォルト値0が挿入されます。

  1. オプション1: MR_COUNTER列にキーワードDEFAULTを指定します。
    INSERT INTO Users VALUES (10, "David", "Morrison", 25, 100000,
        DEFAULT);
    前述の文では、count MR_COUNTERに値DEFAULTを指定しています。
    SELECT * FROM Users;
    出力:
    {"id":10,"firstname":"David","lastname":"Morrison","age":25,"income":100000,"count":0}
  2. オプション2: 必要な列値のみをINSERT文に含めることで、MR_COUNTER列の値をスキップします。
    INSERT INTO Users(id, firstname, lastname) VALUES (20, "John", "Anderson");
    前述の文では、特定の列に値を指定しています。SQLエンジンによって、対応する列にそれらの値が挿入され、MR_COUNTERにデフォルト値0が挿入され、他のすべての列にNULL値が挿入されます。
    SELECT * FROM Users WHERE id = 20;
    出力:
    {"id":20,"firstname":"John","lastname":"Anderson","age":null,"income":null,"count":0}

MR_COUNTERがJSONドキュメントの一部である場合は、MR_COUNTERに値0を明示的に指定する必要があります。

ノート:

  • JSON MR_COUNTERの挿入時にキーワードDEFAULTを指定することはできません。
  • 宣言されたJSON MR_COUNTERフィールドに値を指定せずに、またはキーワードDEFAULTを使用せずに、MR表にデータを挿入しようとすると、エラーが返されます。

次の例では、JSONPersons表に行を挿入しています。peopleドキュメントにJSON MR_COUNTER counterおよびcountが含まれているため、これらのMR_COUNTERに値0を明示的に指定しています。

INSERT INTO JSONPersons VALUES (
   1,
  {
      "firstname":"David",
      "lastname":"Morrison",
      "age":25,
      "income":100000,
      "counter": 0,
      "books" : {
        "Title1" : "Gone with the wind",
        "Title2" : "Oliver Twist",
        "count" : 0
      }      
    }
);
SELECT文では次の結果が表示されます:
{"id":1,"person":{"age":25,"books":{"Title1":"Gone with the wind","Title2":"Oliver Twist","count":0},"counter":0,"firstname":"David","income":100000,"lastname":"Morrison"}};

MR_COUNTERの更新

UPDATE文のSET句を使用して、複数リージョン表内のMR_COUNTERを更新できます。MR_COUNTERの値の増分と減分には、標準の算術計算のみを使用する必要があります。UPDATE句を使用してMR_COUNTERに値を明示的に指定することやそれを表から削除することはできません。
UPDATE Users SET count = count + 10 WHERE id = 10 RETURNING *;
前述の文では、Users表内のcountの値を10ずつ増やしています。RETURNING句では、次の出力がフェッチされます:
{"id":10,"firstname":"David","lastname":"Morrison","age":25,"income":100000,"count":10}
同様に、JSONドキュメント内のMR_COUNTERは、その値を増分または減分することで更新できます。MR_COUNTERには、次のようにパス式を使用してアクセスできます:
UPDATE JSONPersons p SET p.person.books.count = p.person.books.count + 1 WHERE id = 1 RETURNING *;
前述の文では、ネストされたbooksドキュメント内のMR_COUNTER countを1ずつ増分しています。
{"id":1,"person":{"age":25,"books":{"Title1":"Gone with the wind","Title2":"Oliver Twist","count":1},"counter":0,"firstname":"David","income":100000,"lastname":"Morrison"}}

MR_COUNTERを使用して同時変更を処理する方法

複数リージョン表を様々なリージョンに作成した場合、それには同じ定義があります。これは、MR_COUNTERデータ型を定義した場合はそれがリモート・リージョンとローカル・リージョンの両方に存在するということです。すべてのリージョンで、その最後にMR_COUNTERを同時に更新できます。参加リージョン内のすべての複数リージョン表が同期されると、これらの同時変更に関して自動的にマージが実行されて、ユーザーの介入なしでMR_COUNTERの最新の更新が反映されます。

MR_COUNTERを追加または削除するための表の変更

ALTER TABLE文を使用して、MR_COUNTERを追加または削除できます。

MR_COUNTERの追加

MR_COUNTERを追加するには、ALTER TABLE文でADD句を使用します。
ALTER TABLE Users (ADD countTwo INTEGER AS MR_COUNTER);

前述の文では、デフォルト値0でMR_COUNTERとしてcountTwoフィールドをUsers表に追加しています。

SELECT文では次の結果が表示されます:
{"id":10,"firstname":"David","lastname":"Morrison","age":25,"income":100000,"count":10,"countTwo":0}
{"id":20,"firstname":"John","lastname":"Anderson","age":null,"income":null,"count":0,"countTwo":0}
MR_COUNTERは、次のようにJSON列に追加できます:
ALTER TABLE JSONPersons (ADD JsonTwo JSON(counterTwo AS NUMBER MR_COUNTER));
前述の文では、ネストされたJSONドキュメントJsonTwoJSONPersons表に追加され、counterTwoフィールドが値0でMR_COUNTERとして含まれます。
{
  "id" : 1,
  "person" : {
    "age" : 25,
    "books" : {
      "Title1" : "Gone with the wind",
      "Title2" : "Oliver Twist",
      "count" : 1
    },
    "counter" : 0,
    "firstname" : "David",
    "income" : 100000,
    "lastname" : "Morrison"
  },
  "JsonTwo" : {
    "counterTwo" : 0
  }
}

MR_COUNTERの削除

MR_COUNTERを削除するには、ALTER TABLE文でDROP句を使用します。
ALTER TABLE Users (DROP countTwo);

前述の文では、Users表からcountTwo MR_COUNTERが削除されます。

SELECT文では次の結果が表示されます:
{"id":10,"firstname":"David","lastname":"Morrison","age":25,"income":100000,"count":10}
{"id":20,"firstname":"John","lastname":"Anderson","age":null,"income":null,"count":0}
JSONドキュメントとそのMR_COUNTERは、次のように削除できます:
ALTER TABLE JSONPersons (DROP JsonTwo);
前述の文では、JSONPersons表から、ネストされたJSONドキュメントJSONTwoが削除されます。
{
  "id" : 1,
  "person" : {
    "age" : 25,
    "books" : {
      "Title1" : "Gone with the wind",
      "Title2" : "Oliver Twist",
      "count" : 1
    },
    "counter" : 0,
    "firstname" : "David",
    "income" : 100000,
    "lastname" : "Morrison"
  }
}