12cR2.4.5.12での変更点
Oracle NoSQL Database 12cR2.4.5.12 Enterprise Editionで次の変更が行われました。
新機能
-
ユーザーがOracle NoSQL Database表への書込み操作からの変更すべてをサブスクライブできるようにするStreams APIが導入されました。変更は、一連の離散
StreamOperation
クラス・オブジェクトとしてアプリケーションにストリームされます。これらのAPIは、リアクティブ・ストリーム・インタフェースの実装です。ストリームAPIのOracle NoSQLバージョンには、リアクティブ・ストリーム標準によって記述されるAPIと区別するために、接頭辞としてNoSQLが付けられます。たとえば、リアクティブ・ストリームではPublisher
クラスが記述されます。そのクラスのOracle NoSQL Databaseの実装はNoSQLPublisher.
です。詳細は、『Oracle NoSQL Database Streams APIスタート・ガイド』を参照してください。[#24871] -
SQLを使用して単一行のサーバー側での更新を実行するためにUPDATE文が追加されました。
Oracle NoSQL DatabaseのUPDATE文は、標準SQLでのUPDATE文の拡張バージョンです。既存データ・フィールドの値を置換するために使用されるSET句に加えて、配列およびマップでの要素およびフィールドの追加/削除をサポートするためにADD句、PUT句およびREMOVE句が追加されました。さらに、Oracle NoSQLの十分強力なパス式を使用して、更新する複数のターゲット・フィールドを(json内と厳密に型指定されたデータ内のどちらにあるかを)識別したり、場合によっては現在の値に基づいて新しい値を計算できます。ただし、現在の実装で更新できるのは単一行のみです。これは、WHERE句で完全な主キーを指定する必要があることを意味します。
例として、2つの列(整数のid列およびJSON型のinfo列)のみを持つPeopleと呼ばれる表があるとします。また、次の行を更新するものとします。
{ "id" : 0, "info" : { "firstName" : "John", "lastName" : "Doe", "profession" : "software engineer", "income" : 200000, "address" : { "city" : "San Fransisco", "state" : "CA", "phones" : [ { "areacode":415, "number":2840060, "kind":"office" }, { "areacode":650, "number":3789021, "kind":"mobile" }, { "areacode":415, "number":6096010, "kind":"home" } ] }, "children": { "Anna" : { "age" : 10, "school" : "ABC", "friends" : ["John", "Maria"] }, "Ron" : { "age" : 2 }, "Mary" : { "age" : 7, "school" : "XYZ", "friends" : ["Mark"] } } } }
次のUPDATE文は、前述の行の様々なフィールドを更新します。
update People p set p.info.profession = "surfing instructor", set p.info.address.city = "Santa Cruz", set p.info.income = $ / 10, set p.info.children.values().age = $ + 1, add p.info.address.phones 0 { "areacode":831, "number":5294368, "kind":"mobile" } remove p.info.address.phones[$element.kind = "office"] put p.info.children.Ron { "friends" : ["Julie"] }, where id = 0 returning *
前述の文の最後にあるRETURNING句は、更新後に行全体を返す必要があることを指定しています。したがって、この文の結果は次のようになります。
{ "id" : 0, "info" : { "firstName" : "John", "lastName" : "Doe", "profession" : "surfing instructor", "income" : 20000, "address" : { "city" : "Santa Cruz", "state" : "CA", "phones" : [ { "areacode":831, "number":5294368, "kind":"mobile" }, { "areacode":650, "number":3789021, "kind":"mobile" }, { "areacode":415, "number":6096010, "kind":"home" } ] }, "children": { "Anna" : { "age" : 11, "school" : "ABC", "friends" : ["John", "Maria"] }, "Ron" : { "age" : 3, "friends" : ["Julie"] }, "Mary" : { "age" : 8, "school" : "XYZ", "friends" : ["Mark"] } } } }
最初の2つのSET句は、John Doeの職業と市町村を変更します。3番目のSETは、収入を10分の1まで削減します。このSETでは、暗黙的に宣言された$変数がSETのターゲット・アイテム(p.info.income式の結果)にバインドされます。4番目のSETは、Johnの子の年齢を1つ増やします。ここでもう一度、$変数の使用に注意してください。式p.info.children.values().ageは3つの年齢を返します。SETはこれらの年齢を反復し、$変数を各年齢にバインドし、各年齢の式$ + 1を計算し、新しい値で年齢を更新します。
ADD句は、phone配列内の位置0に新しい電話番号を追加します。REMOVEは、すべての勤務先電話番号(この例では1つのみ)を削除します。PUT句はRonの友人を追加します。この句では、式p.info.children.RonはRonの子に関連付けられた値を返します。この値はマップ(jsonオブジェクト{" age ": 3})であり、更新のターゲットになります。PUTの2番目の式({" friends ":[" Julie "]})は、新しいマップを作成して返します。このマップのフィールドがターゲット・マップに追加されます。[#26161]
-
キャスト式の変更点。
-
レコードをマップにキャストできるようになりました。これにより、ユーザーはレコードをjsonオブジェクトにキャストできるようになります。
-
レコードにマップをキャストできます。Oracleにはレコード・コンストラクタがないため、これが更新のために必要になります。そのため、ユーザーがレコード全体を新しいレコードで置き換える場合、ユーザーがマップを作成すると、このマップが更新文によってレコードにキャストされます。
-
前の実装では、入力値がJSONのサブタイプであった場合、JSONへのキャストは操作できませんでした。ただし、たとえば、ARRAY(INT)はJSONのサブタイプであるため、これは実際にはバグでした。また、ARRAY(INT)をJSONにキャストする場合は、ARRAY(JSON)型の配列を作成する必要があります。したがって、ターゲット・タイプがJSONである場合、現在の実装では、入力値に含まれる配列/マップが出力値のARRAY (JSON)/MAP(JSON)にキャストされることを確認します。さらに、Oracleではマップへのレコードのキャストが可能になったため、JSONへのレコードのキャストは、MAP(JSON)へのレコードのキャストとして扱われるようになりました。以前は、この場合はエラーが発生していました。[#26161]
-
-
SQL関数
seq_concat
が追加されました。この関数は単に、引数式によって返されるシーケンスの連結を返します。[#26161] -
TIMESTAMPフィールドから一時フィールドを抽出するためのSQL関数が追加されました。[#26046]
-
ディスクの使用を実施するためにストレージ・ディレクトリのサイズが使用されるようになり、ディスク使用量を監視するための新しい統計が提供されています。すべてのアプリケーションで次のことを実行することをお薦めします。
-
すべてのRNに対してストレージ・ディレクトリおよびサイズを指定します。
-
新しいavailableLogSize統計を使用してディスクの使用量を監視し、この値がゼロになる前に十分時間をとって修正アクションを実行します。
ストレージ・エンジンでは連絡不可のノードへの潜在的なレプリケーション用としてデータ・ファイルが予約されるため、ストレージ・サイズを指定することが重要です。このリリースでは、潜在的なレプリケーション用としてより多くの予約済ファイルが保持されます。ストレージ・サイズが指定されていない場合、ボリューム上のすべての空き領域(空き領域の5GBを差し引いた量)が最終的に使用されます。
監視されない場合または修正処理が行われない場合、データ・セットのサイズが大きくなると、ストレージ・サイズ(またはボリューム・サイズ)を超過する危険性があります。起こる可能性は高くありませんが、この問題は、スナップショットの削除を怠ることなどにより、構成エラー(キャッシュ・サイズが小さすぎる場合など)が原因で発生する場合もあります。現在は、ディスク使用量が内部的に監視され、ストレージ・サイズ(またはボリューム・サイズ)を超過する危険性がある場合は書込み操作が拒否されるようになりました。この場合でも、読取り操作は引き続き可能です。以前は、ボリュームがいっぱいになるとRNは機能しなくなりました。つまり、操作を実行できなくなりました。読取り操作を許可することにより、この状況で可用性を一部確保できるようになりました。また、指定されたストレージ・サイズに関係なく、ボリューム上に少なくとも5GBの空き領域が確保されることが保証されています。
availableLogSize
統計は、書込み操作に使用できる領域の量を表し、書込み操作の実行が必要な場合は予約済データ・ファイルが自動的に削除されるようになっています。このように自動的に削除される予約済ファイルが存在するため、ファイル・システム内のディスク使用量の監視は意味がありません。availableLogSize
統計は、いくつかの新しい統計の1つです。-
activeLogSize
-- すべてのアクティブなデータ・ファイルに使用されるバイト数: 基本の操作に必要なファイル。 -
reservedLogSize
-- すべての予約済データ・ファイルに使用されるバイト数: クリーン・アップされており、保護されていない場合は削除できます。 -
protectedLogSize
-- すべての保護済データ・ファイルに使用されるバイト数: 一時的に保護される予約済ファイルのサブセットであり、削除できません。 -
protectedLogSizeMap
-- 保護する側のエンティティ名から保護されるサイズ(バイト単位)へのマップとしてのprotectedLogSize
のブレークダウン。 -
availableLogSize
-- 保護されていない予約済ファイルが削除された場合に書込み操作に使用できるバイト数: 空き領域 +reservedLogSize
-protectedLogSize
。 -
totalLogSize
-- ディスク上のデータ・ファイルに使用される合計バイト数:activeLogSize
+reservedLogSize
。
これらの統計は
.stat
ファイルに含まれ、JMXoracle.kv.repnode.envmetric
型を使用して監視できます。JMX出力では、これらの統計名はログ・クリーニング(ディスク・ガベージ・コレクション)統計グループ内にあるため、接頭辞Cleaning_が付きます(例: Cleaning_availableLogSize)。新しいストアの場合、ストレージ・サイズはmakebootconfigで
-storagedirsize
引数を使用して指定します。既存のストアの場合、change-storagedir
プランを使用してストレージ・サイズを追加(または変更)できます。どちらの場合も、容量が1の場合でも-storageDir
を指定する必要があることに注意してください。ストレージ・ディレクトリのサイズを指定することが推奨されるため、
-storagedir
が指定されているが-storagedirsize
が指定されていない場合は、makebootconfigによって警告が出力されるようになりました。[#25220] -
-
Verify Configuration
では、ユーザーが-storagedirsize
と-rootdirsize
を指定しない場合、警告が発行されるようになりました。ストアのインストール時には、これらのパラメータを設定してディスク領域の管理に役立てることをお薦めします。[#26187] -
表名のサイズが32文字から256文字に拡張されました。[#26021]
バグとパフォーマンスの修正
-
問合せによる索引の使用が改善されました。
以前のリリースでは、パス・フィルタリング・ステップ内に表示される条件はsargableとみなされていませんでした。つまり、索引スキャンの開始点または停止点の判断に使用されることはありませんでした。現在のリリースでは、この制限が解除されています。例として、次の問合せを考えてみます。
select id from foo f where f.info.address.phones[408 <= $element.areacode and $element.areacode <= 650].kind =any "work"
(info.address.phones[].areacode,
info.address.phones[].kind)
に対する索引が存在する場合、問合せ内のすべての述語を索引スキャンに使用できるようになりました。このため、この索引に対するスキャンはareacode 408で開始し、areacode 650の直後に停止します。スキャン中、kindフィールドがworkと等しいエントリのみが選択されます。この修正の前は、索引が問合せによって選択された場合は全索引がスキャンされ、このスキャン中にkindに対する等価述語のみが適用されていました。このリリースでは、パス・フィルタ述語に加えて、EXISTS述語も潜在的にsargableな述語として扱われます。たとえば、次の問合せを考えてみます。
select id from foo f where exists f.info.address.state and exists f.info.address.phones.areacode
この場合、
(info.address.state,
info.address.phones[].areacode)
に対する索引がある場合、問合せ内の述語は両方ともsargableです。索引の2つの範囲がスキャンされます。最初の範囲は索引の先頭から始まり、stateフィールドの値としてEMPTYを持つ最初のエントリで終わります。2番目の範囲は、このEMPTY値の直後から始まり、索引の最後で終了します。それぞれのスキャン中に、areacodeフィールドでEMPTY値を持つエントリが消去されます。[#26044] -
問合せに2次索引が使用され、索引定義の一部ではない主キー列の述語も含まれる場合のバグが修正されました。ある条件下では、主キー列の述語が索引スキャンの開始/停止述語として使用されていました。これは不可能であり、問合せのコンパイル中に
IndexOutOfBoundsException
が発生します。次に例を示します。create table t1(id integer, name string, primary key(id)); create index idx1 on t1(name); select * from t1 where name = "alex" and id > 0
このバグ修正では、id列の条件は開始/停止述語としては使用されなくなりましたが、索引フィルタ処理述語としては使用されています。[#26358]
-
トポロジへのアービタを追加、移動または削除するためにplan failoverコマンドに対する機能が追加されました。[#25269]
-
SQL問合せ処理のパフォーマンス・バグが修正されました。表メタデータをフェッチするための不要なリモート・コールが削除されました。このコールでは、各SQL問合せに対しての1回かぎりのオーバーヘッドが約2ミリ秒増えていました。これは、アクセスする行が少ない問合せの場合に、特に行がメモリーにキャッシュされるときに大きなオーバーヘッドとなります。たとえば、メモリーにキャッシュされた単一の行にアクセスしてこれを返す問合せのレイテンシは、同等の表イテレータAPIコールの5倍の時間がかかっていました。[#26232]
-
TableQuery操作がサーバーから別のサーバーに転送されたときに発生する問合せのバグが修正されました。たとえば、これはパーティションの移行中に発生することがあります。このバグはTableQueryのシリアライズ・メソッドにありました。なぜなら、このメソッドでは、TableQueryがクライアントからサーバーに送信されるときにのみシリアライズが発生するとみなしていたためです。[#26385]
-
ユーザーは
PASSWORD LIFETIME
をゼロに設定できるようになりました。値が0日に設定されている場合、パスワードは期限切れになりません。これが修正される前は、ユーザーがALTER USER admin PASSWORD LIFETIME 0 DAYSを発行しようとすると、文は失敗し、「Time value must not be zero or negative」というメッセージが表示されていました。[#26040] -
JavaドライバがJavaロガーを構成する方法が変更され、追加のログ・ハンドラを構成しやすくなりました。kv.oracleロガー用のファイル・ロギング・ハンドラを指定することにより、ファイルにロギング出力を送信するようアプリケーションを構成できるようになりました。[#26134]
-
セッション・タイムアウト後でも
AuthenticationRequiredException
を返さず、セキュアなKVstoreに対して問合せを実行できるというバグが修正されました。[#26250], [#26249] -
メソッド
oracle.kv.table.Index.createIndexKey(RecordValue value)
はこのリリースで非推奨になっています。このメソッドでは、マップまたは配列の要素を含むマルチキー索引の索引キーを作成できないため、複数の索引エントリ、または単一の行に対する個別のIndexKey値が生成される可能性があります。[#26211] -
非主キー列を追加してキーのみの表を変更すると、後続の問合せおよび索引の作成が失敗するというバグが修正されました。このバグは、R4.4にも存在します。[#26354]
-
SHOW AS JSON USERS
およびSHOW AS JSON ROLE
ロールの出力が修正され、正しいJSON形式で結果が出力されるようになりました。出力形式が正しくないため、アプリケーションで解析の問題が発生していました。[#26355] -
4.2より前のリリースから4.2、4.3または4.4にアップグレードする場合、ERROR状態の未処理のプランが複数存在すると、起動時に管理が失敗する可能性があります。このバグはこのリリースで修正されました。[#26303]
ユーティリティの変更点
-
管理CLIおよびpingユーティリティ用に2つの新しい引数
-registry-open-timeout
と-registry-read-timeout
が導入されました。これらを使用して、レジストリ要求に使用するソケットに関連付けたオープン・タイムアウトと読取りタイムアウトをミリ秒単位で構成します。[#24164]
ストレージ・エンジンの変更点(JE 7.5)
-
Azul Zulu JVMとの互換性の問題が修正されました。以前は、Zuluを使用したときに次の例外が発生していました。[#26163]
The database environment could not be opened: java.lang.IllegalStateException: Could not access Zing management bean. Make sure -XX:+UseZingMXBeans was specified.
-
ネットワークのリストアの実行時にOutOfMemoryErrorを引き起こす可能性のあるバグが修正されました。これが原因で、RNが不必要に再起動し、ネットワーク・リストアが再試行されることがあります。(ネットワーク・リストアは、RNが一定期間停止しており、シャード内のマスター・ノードを遅延させている場合に使用されます。)[#26305]
-
なんらかの理由で前のネットワーク・リストアが中止されたか不完全であった後にネットワーク・リストアの実行を妨げる可能性のあるバグが修正されました。(ネットワーク・リストアは、RNが一定期間停止しており、シャード内のマスター・ノードを遅延させている場合に使用されます。)
たとえば、最初のネットワーク・リストア時にRNプロセスが強制終了され、その後、別のネットワーク・リストアが試行された場合に、これが発生することがあります。この問題は、比較的大きなデータ・セットがある環境でのみ発生することがあります。特に、10億以上の書込みトランザクションが実行された場合です。スタック・トレースの例を次に示します。
java.lang.NumberFormatException: For input string: "7473413648" at java.lang.NumberFormatException.forInputString( NumberFormatException.java:65) at java.lang.Integer.parseInt(Integer.java:583) at java.lang.Integer.parseInt(Integer.java:615) at com.sleepycat.je.rep.InsufficientLogException.init( InsufficientLogException.java:218) at com.sleepycat.je.rep.impl.RepImpl.handleRestoreRequired( RepImpl.java:2296) at com.sleepycat.je.recovery.RecoveryManager.findEndOfLog( RecoveryManager.java:543) at com.sleepycat.je.recovery.RecoveryManager.recover( RecoveryManager.java:339) at com.sleepycat.je.dbi.EnvironmentImpl.finishInit( EnvironmentImpl.java:841) at com.sleepycat.je.dbi.DbEnvPool.getEnvironment(DbEnvPool.java:222) at com.sleepycat.je.Environment.makeEnvironmentImpl(Environment.java:267) at com.sleepycat.je.Environment.init(Environment.java:252) at com.sleepycat.je.rep.ReplicatedEnvironment.init( ReplicatedEnvironment.java:607) at com.sleepycat.je.rep.ReplicatedEnvironment.init( ReplicatedEnvironment.java:466) at oracle.kv.impl.rep.RepEnvHandleManager.openEnv( RepEnvHandleManager.java:628) at oracle.kv.impl.rep.RepEnvHandleManager.renewRepEnv( RepEnvHandleManager.java:465) at oracle.kv.impl.rep.RepNode.startup(RepNode.java:913)
これは修正されました。修正されていない場合、問題の回避策として、RNノード上の.jdbファイルをすべて削除し、RNを再起動します。[#26311]