1 RDFナレッジ・グラフの概要

セマンティク・テクノロジに対するOracle Spatial and Graphのサポートは、主にResource Description Framework (RDF)およびWeb Ontology Language (OWL)のサブセットで構成されています。これらの機能は、Oracle Spatial and GraphのRDFナレッジ・グラフ機能と呼ばれます。

RDFナレッジ・グラフ機能を使用すると、Oracleデータベースに1つ以上のセマンティク・ネットワークを作成できます。各ネットワークには、セマンティク・データ(RDFデータとも呼ばれる)が含まれています。

この章では、読者がRDFおよびOWLに関する主要な概念({主語、述語、目的語}のトリプル、{主語、述語、目的語}のクアッド、URI、空白ノード、プレーン・リテラル、型付きリテラル、オントロジなど)についてよく理解していることを前提とします。こうした概念の詳細は説明しないかわりに、各概念がどのようにOracleに実装されているかを重点的に解説します。

セマンティク・データを操作するためのPL/SQLサブプログラムは、SEM_APISパッケージに含まれています。詳細は、「SEM_APISパッケージのサブプログラム」を参照してください。

RDFサポートおよびOWLサポートは、Oracle Spatial and Graphの機能です。これらの機能を使用するには、Oracle Spatial and Graphをインストールする必要があります。ただし、RDFおよびOWLの使用は、空間データに制限されません。

ノート:

リリース12.2よりも前のOracle Databaseで作成されたセマンティク・データがある場合は、「リリース12.2よりも前のセマンティク・データに必要な移行作業」を参照してください。

OWLの概念とOracle DatabaseによるOWL機能のサポートの詳細は、「OWLの概要」を参照してください。

ノート:

このマニュアルで説明している操作を実行するには、「RDFセマンティク・グラフ・サポートを有効にする」に示すように、前もってデータベースでRDFセマンティク・グラフ・サポートを有効にして他の前提条件も満たす必要があります。

1.1 Oracleセマンティク・テクノロジ・サポートの概要

Oracle Databaseでは、セマンティク・データとオントロジを格納し、セマンティク・データを問い合せることや、エンタープライズ・リレーショナル・データに対してオントロジ支援問合せを実行することができ、また、付属の推論またはユーザー定義の推論を使用して、セマンティク・データに対する問合せ機能を拡張することも可能です。

図1-1に、これらの機能の相互関係を示します。

図1-1 Oracleのセマンティク機能

図1-1の説明が続きます
「図1-1 Oracleのセマンティク機能」の説明

図1-1に示されているとおり、データベースには、セマンティク・データおよびオントロジ(RDF/OWLモデル)に加え、従来のリレーショナル・データが含まれます。セマンティク・データをロードするには、バルク・ロードが最も効率的な方法ですが、トランザクション型のINSERT文を使用してデータを増分ロードすることも可能です。

ノート:

Oracle Databaseリリース11.1より前のリリースで作成した既存のセマンティク・データを使用する場合、「RDFセマンティク・グラフ・サポートの有効化」の手順に従ってデータをアップグレードする必要があります。

セマンティク・データおよびオントロジは問合せ可能です。また、セマンティク・データや従来のリレーショナル・データに対してオントロジ支援問合せを実行し、セマンティク関係を検出することもできます。オントロジ支援型問合せを実行するには、SEM_RELATED演算子を使用します(「リレーショナル・データに対する照会でのセマンティク演算子の使用」を参照)。

セマンティク・データに対する問合せ機能は、推論を使用して拡張できます。推論では、ルールベースのルールを使用します。推論により、データおよびルールに基づいて論理的な推測を行うことができます。推論でルールおよびルールベースを使用する方法の詳細は、「推論: ルールとルールベース」を参照してください。

1.2 セマンティク・データのモデル化

セマンティク・データには、その形式意味論に加え、有向グラフを使用して効率的にモデル化される単純なデータ構造が含まれます。

メタデータ文は、トリプルとして表現されます。ノードはトリプルの2つの部分を示すために使用され、3番目の部分はノード間の関係を記述する有向リンクによって示されます。トリプルは、セマンティク・データ・ネットワークに格納されます。また、データベース・ユーザーにより作成された特定のセマンティク・データ・モデルに関する情報も保持されます。ユーザーにより作成されたモデルは、モデル名を持ち、指定した表の列に格納されているトリプルを参照します。

文は、{主語(リソース)、述語(プロパティ)、目的語(値)}のトリプルで表現されます。このマニュアルでは、{主語、プロパティ、目的語}を使用してトリプルを記述し、という用語とトリプルという用語は、同義的に使用される場合があります。各トリプルは、特定のドメインに関する完全で一意のファクトであり、有向グラフのリンクで表現されます。

1.3 データベースのセマンティク・データ

Oracle Databaseのセマンティク・データは、1つ以上のセマンティク・ネットワークに格納されます。

表のエントリがセマンティク・ネットワークであり、各セマンティク・ネットワークがデータベース・スキーマ(通常のデータベース・ユーザー・スキーマまたはオラクル社が提供するMDSYSスキーマ)の下にある場合、すべてのトリプルが解析されてシステムに格納されます。{主語、プロパティ、目的語}のトリプルは、1つのデータベース・オブジェクトとして処理されます。そのため、複数のトリプルを含む単一の文書は、複数のデータベース・オブジェクトになります。

トリプルのすべての主語および目的語は、セマンティク・データ・ネットワークのノードにマップされます。プロパティは、主語を開始ノード、目的語を終了ノードとするネットワーク・リンクにマップされます。使用可能なノード・タイプは、空白ノード、URI、プレーン・リテラルおよび型付きリテラルです。

URIの指定とデータベースへのセマンティク・データの格納には、次の要件が適用されます。

  • 主語は、URIまたは空白ノードである必要があります。

  • プロパティは、URIである必要があります。

  • 目的語は、URI、空白ノードまたはリテラルのいずれのタイプでもかまいません。(ただし、NULL値およびNULL文字列はサポートされません。)

1.3.1 セマンティク・ネットワーク

セマンティク・ネットワークは、RDFデータ(セマンティク・データ)を保持する一連の表およびビューです。セマンティク・ネットワークはインストール時には作成されません。データベース・ユーザーは、RDFデータをデータベースに格納する前に、SEM_APIS.CREATE_SEM_NETWORKを明示的にコールしてセマンティク・ネットワークを作成する必要があります。

セマンティク・ネットワークには、特にRDFトリプルまたはクワッドを格納するためのRDF_LINK$表が含まれます。デフォルトでは、RDF_LINK$表は、モデルのセットにリスト・パーティション化されています。モデルは、RDFトリプルまたはクワッドを格納するためのユーザー作成コンテナです。

RDF_LINK$表はオプションでリスト-ハッシュ・コンポジット・パーティション化を使用し、各モデル・パーティションが述語のハッシュによってサブパーティション化されます。コンポジット・パーティション化では、より優れたデータ・セットや問合せオプティマイザ統計を改善することで、大規模なデータ・セットでSPARQL問合せのパフォーマンスを向上させることができます。コンポジット・パーティション化を有効にする方法の詳細は、次を参照してください。

セマンティク・ネットワークは、MDSYSスキーマまたは通常のデータベース・ユーザー・スキーマで作成し、所有できます。

  • ネットワークがMDSYSスキーマで作成される場合は、データベース全体で使用可能な名前のないセマンティク・ネットワークです。

    単一の無名ネットワークを持つことが、Oracle Databaseリリース19cより前で使用可能なただ1つのシナリオでした。その使用は引き続きサポートされていますが、リリース19c以降に作成されるネットワークではお薦めしません。

  • データベースにMDSYSスキーマのネットワークが存在するかどうかに関係なく、1つ以上の通常のデータベース・ユーザー・スキーマに1つ以上のセマンティク・ネットワークを作成できます。このようなネットワークはそれぞれ、スキーマプライベート・セマンティク・ネットワークと呼ばれます。

    スキーマプライベート・ネットワークの使用をお薦めします。

単一のデータベースまたはプラガブル・データベースに、MDSYS所有のネットワークと1つ以上のスキーマプライベート・ネットワークを持つことができます。

既存のMDSYS所有セマンティク・ネットワークを、SEM_APIS.MOVE_SEM_NETWORK_DATAおよびSEM_APIS.APPEND_SEM_NETWORK_DATAプロシージャを使用して共有スキーマプライベート・セマンティク・ネットワークに移行できます。詳細は、「セマンティク・ネットワークの移動、リストアおよび追加」を参照してください。

1.3.1.1 スキーマプライベート・セマンティク・ネットワーク

スキーマプライベート・セマンティク・ネットワークでは、関連付けられたデータベース・オブジェクトがネットワーク所有者のスキーマ内に作成され、ネットワーク所有者がそれらのオブジェクトに対する排他的な権限を持ちます。(DBAユーザーにはそのような権限もあり、ネットワーク所有者またはDBAは他のユーザーの権限を付与および取り消すことができます)。

スキーマプライベート・セマンティク・ネットワークには、次のような利点があります。

  • 複数のユーザーが表および索引を共有しないため、セキュリティと分離が向上します。

    ネットワーク所有者のスキーマには、すべてのセマンティク・ネットワーク・データベース・オブジェクトが含まれ、ネットワーク所有者はデフォルトでそれらのオブジェクトに対する排他的な権限を持ちます。

    スキーマプライベート・セマンティク・ネットワークは、データベース・オブジェクトが複数のデータベース・ユーザー間で共有されないため、より優れた分離を提供します。ただし、適切な権限を付与した後、ネットワーク所有者は自分のスキーマプライベート・セマンティク・ネットワークと他のユーザーを共有できます。

  • 通常のユーザーは、自身のネットワークにおいて、索引の作成やネットワーク全体の統計収集などの管理操作を実行できます。

    ネットワーク所有者は、DBA権限を必要とすることなくネットワーク上で管理操作を実行できます。(対照的に、MDSYS所有のネットワークでは、管理操作を実行するためにDBA権限が必要です)。

    1つのデータベース、PDBまたはそれ以上のスキーマに共存する複数のスキーマプライベート・セマンティク・ネットワークが共存し、RDFデータの様々なセットに対してカスタム・データ型索引付けスキームを使用できます。たとえば、NETWORK1には空間データ型索引のみを含めることができますが、NETWORK2にはテキスト・データ型索引しかありません。

ほとんどのSEM_APISパッケージ・サブプログラムには、スキーマプライベート・セマンティク・ネットワークをサポートするためのnetwork_ownerおよびnetwork_nameパラメータが追加されました。スキーマプライベート・セマンティク・ネットワークは、ネットワーク所有者とネットワーク名の2要素の組合せで識別されます。ネットワーク名は、ネットワークを作成したSEM_APIS.CREATE_SEM_NETWORKコールの最後の2つのパラメータで指定されます。

次の表に、network_ownerおよびnetwork_nameパラメータの使用方法を、それを含むサブプログラムで示します。

表1-1 network_ownerおよびnetwork_nameのパラメータ

パラメータ名 説明
network_owner ネットワークを所有するスキーマの名前。デフォルトはNULLです。
  • スキーマプライベート・ネットワークの場合、nullではなく、通常のデータベース・ユーザー(MDSYSまたは事前定義済の別のOracle提供ユーザーではない)を指定する必要があります。

  • MDSYS所有ネットワークの場合、nullである必要があります。

network_name ネットワーク名です。デフォルトはNULLです。
  • スキーマプライベート・ネットワークの場合、nullではなく、ネットワークの名前を指定する必要があります。

    名前は、ネットワーク所有者のスキーマ内で一意である必要があります。たとえば、スキーマSCOTTはNET1という名前の2つのネットワークを持つことはできませんが、スキーマSCOTTとANNAはそれぞれNET1という名前のネットワークを持つことができます。

  • MDSYS所有ネットワークの場合、nullである必要があります。

1.3.1.2 セマンティク・ネットワーク・ユーザーのタイプ

スキーマプライベート・セマンティク・ネットワークとMDSYS所有セマンティク・ネットワークは、ネットワーク作成者、ネットワーク所有者およびネットワーク・ユーザーという3つの主要なタイプのユーザーに基づいて区別できます。

  • ネットワーク作成者は、SEM_APIS.CREATE_SEM_NETWORKを起動するユーザーです。ネットワーク作成者は、DBA権限を持つデータベース・ユーザーか、ネットワーク所有者と同じユーザーです。

  • ネットワーク所有者は、セマンティク・ネットワークを構成する表、トリガーおよびビューを保持するユーザーです。

  • ネットワーク・ユーザーは、セマンティク・ネットワーク上で操作を実行するデータベース・ユーザーです。

    このマニュアルの多くの例で、RDFUSERという名前がサンプル・ネットワーク・ユーザー名として指定されています。その名前文字列について特別なことはありません。SCOTTANNAMARKETINGなど任意のデータベース・ユーザーの名前を使用できます。

    スキーマプライベート・ネットワークの場合、ネットワーク所有者は最初はネットワーク・ユーザーのみです。(ただし、他のデータベース・ユーザーにネットワークに対する権限を付与して、追加の潜在的ネットワーク・ユーザーにすることができます。)

1.3.1.3 セマンティック・ネットワーク・オブジェクトの命名規則

セマンティック・ネットワーク・データベース・オブジェクトは、特定の命名規則に従います。

スキーマプライベート・ネットワーク内のすべてのセマンティク・ネットワーク・データベース・オブジェクトに、接頭辞としてNETWORK_NAME#が付いています(たとえば、MDSYS.SEM_MODEL$ではなくUSER3.MYNET#SEM_MODEL$)。このマニュアルでは、接頭辞の後のデータベース・オブジェクト名の一部を使用して、オブジェクトを参照します。つまり、SEM_MODEL$は、MDSYS所有のネットワークの場合はMDSYS.SEM_MODEL$、スキーマプライベート・セマンティク・ネットワークの場合はNETWORK_OWNER.NETWORK_NAME#SEM_MODEL$を指します。

1.3.1.4 セマンティク・ネットワークのRDF_PARAMETER表

MDSYS.RDF_PARAMETER表は、インストールされたバージョンなどデータベース全体のRDFセマンティク・グラフのインストール情報を保持し、MDSYSセマンティク・ネットワークのネットワーク固有の情報を保持します。

MDSYS.RDF_PARAMETER表はインストール時に作成され、常に存在します。MDSYSセマンティク・ネットワークの存在に依存しません。

スキーマプライベート・セマンティク・ネットワークでは、NETWORK_NAME#RDF_PARAMETER表にネットワーク固有の情報(ネットワーク圧縮設定や、スキーマプライベート・ネットワークで使用されるRDFCTXまたはRDFOLSポリシーなど)が保持されます。

スキーマプライベートのNETWORK_NAME#RDF_PARAMETER表は、NETWORK_NAMEセマンティク・ネットワークの存在に依存します。この表は、スキーマプライベート・ネットワークの作成時に作成され、スキーマプライベート・ネットワークが削除されるときに削除されます。

1.3.1.5 MDSYSからスキーマプライベート・セマンティク・ネットワークへの移行

既存のMDSYS所有セマンティク・ネットワークを、SEM_APIS.MOVE_SEM_NETWORK_DATAおよびSEM_APIS.APPEND_SEM_NETWORK_DATAプロシージャを使用して共有スキーマプライベート・セマンティク・ネットワークに移行できます。詳細は、「セマンティク・ネットワークの移動、リストアおよび追加」を参照してください。

1.3.1.6 スキーマプライベート・セマンティク・ネットワークの共有

スキーマプライベート・ネットワークの作成後、必要に応じて共有できます。つまり、ネットワーク所有者以外の他のデータベース・ユーザーが使用できるようにできます。その他のユーザーは、次のいずれかのアクセス機能を持つことができます。

  • RDFデータへの読取り専用アクセス。これにより、ネットワーク内のセマンティク・データを問い合せることができるようになります。
    RDFネットワークへの読取り専用アクセス権または問合せ専用アクセス権の付与は、次の方法で行うことができます。
    1. ネットワーク所有者が、OPTIONSパラメータにQUERY_ONLY=Tを指定して単一のコマンドSEM_APIS.GRANT_NETWORK_ACCESS_PRIVSを使用して実行。
    2. ネットワーク所有者またはモデル所有者が、ネットワーク内の個々のモデルに対してQUERYSELECTなどの適切な権限を指定してSEM_APIS.GRANT_MODEL_ACCESS_PRIVSを使用して実行。

    詳細は、例1-1を参照してください。

  • セマンティク・モデルと伴意の作成、変更または削除、およびRDFデータの読取り、挿入、変更または削除など、ネットワーク内のRDFオブジェクトおよびデータに対する読取り/書込みアクセス権

    読取りアクセス権と書込みアクセス権の両方を付与するステップの論理的順序は、次のとおりです。

    1. DBAが、ネットワーク所有者にネットワーク共有権限を付与する必要があります。これは、指定されたネットワーク所有者に対して1回のみ実行する必要があります。
    2. ネットワーク所有者は、共有のための特定のネットワークを有効にする必要があります。これは、指定されたネットワークに対して1回のみ実行する必要があります。
    3. ネットワーク所有者は、ネットワークへのアクセスを許可されるユーザーにネットワーク・アクセス権限を付与する必要があります。

      これらの各付与は、その後、必要に応じて取り消すことができます。

    詳細は、例1-2を参照してください。

ノート:

ネットワークに対して前述のアクセス機能を持つユーザーは、ネットワークのディクショナリ表およびメタデータ表にのみアクセスできます。ユーザーが所有していないモデルおよび伴意は、ネットワーク所有者または個々のモデルの所有者がSEM_APIS.GRANT_MODEL_ACCESS_PRIVまたはSEM_APIS.GRANT_MODEL_ACCESS_PRIVSサブプログラムを使用して、ネットワーク内の個々のモデルまたは伴意に対する適切な権限をユーザーに付与しないかぎりアクセスできません。

例1-1 ネットワークの共有と別のユーザーへの問合せ専用権限の付与

次の例では、ユーザーRDFUSERが所有するNET1というネットワークを共有しています。RDFUSERは、NET1に対する問合せ専用アクセス権をユーザーRDFQに付与します。

-- As RDFUSER, create a schema-private network owned by RDFUSER named NET1
CONNECT rdfuser/<password>;
EXECUTE SEM_APIS.CREATE_SEM_NETWORK('RDFTBS',network_owner=>'RDFUSER',network_name=>'NET1');

-- As RDFUSER, grant query only network access privilege for NET1 to RDFQ
EXECUTE SEM_APIS.GRANT_NETWORK_ACCESS_PRIVS(network_owner=>'RDFUSER',network_name=>'NET1',network_user=>'RDFQ', options=>' QUERY_ONLY=T ');

-- As RDFUSER, create a semantic model M1 in network NET1
EXECUTE SEM_APIS.CREATE_SEM_MODEL('M1',null,null,network_owner=>'RDFUSER',network_name=>'NET1');

-- Check metadata
SELECT *
FROM rdfuser.net1#sem_model$;

-- Insert some data
INSERT INTO rdfuser.net1#rdft_m1(triple)
VALUES (SDO_RDF_TRIPLE_S('M1','<urn:person1>','<urn:name>','"Peter"','RDFUSER','NET1'));
COMMIT;

-- Allow RDFQ to select and query a model that RDFUSER owns
EXECUTE SEM_APIS.GRANT_MODEL_ACCESS_PRIVS('M1','RDFQ',sys.odcivarchar2list('SELECT','QUERY'),network_owner=>'RDFUSER',network_name=>'NET1');

-- As RDFQ, verify that model M1 is visible for querying
CONNECT rdfq/<password>;
SELECT * 
FROM rdfuser.net1#rdf_model$ 
WHERE model_name='M1';

-- Query with SEM_MATCH
SELECT s$rdfterm, p$rdfterm, o$rdfterm
FROM TABLE(SEM_MATCH(
'SELECT ?s ?p ?o
 WHERE { ?s ?p ?o }'
,SEM_MODELS('M1')
,null,null,null,null
,' PLUS_RDFT=VC '
,null,null
,'RDFUSER','NET1'));

例1-2 ネットワークの共有と別のユーザーへの読取りおよび書込み権限の付与

次の例では、ユーザーRDFUSERが所有するNET1という名前のネットワークをユーザーRDFUSER2と共有しています。また、RDFUSERは、NET1に対する問合せ専用アクセス権をユーザーRDFUSER3に付与します。

-- As RDFUSER, create a schema-private network owned by RDFUSER named NET1
CONNECT rdfuser/<password>;
EXECUTE SEM_APIS.CREATE_SEM_NETWORK('RDFTBS',network_owner=>'RDFUSER',network_name=>'NET1');

-- As a DBA, grant required privileges for network sharing to RDFUSER
CONNECT system/<password>;
EXECUTE SEM_APIS.GRANT_NETWORK_SHARING_PRIVS(network_owner=>'RDFUSER');

-- As RDFUSER, enable sharing for NET1
CONNECT rdfuser/<password>;
EXECUTE SEM_APIS.ENABLE_NETWORK_SHARING(network_owner=>'RDFUSER',network_name=>'NET1');

-- As RDFUSER, grant network access privileges for NET1 to RDFUSER2
EXECUTE SEM_APIS.GRANT_NETWORK_ACCESS_PRIVS(network_owner=>'RDFUSER',network_name=>'NET1',network_user=>'RDFUSER2');

-- As RDFUSER2, create a semantic model M2 in network NET1
CONNECT rdfuser2/<password>;
EXECUTE SEM_APIS.CREATE_SEM_MODEL('M2',null,null,network_owner=>'RDFUSER',network_name=>'NET1');

-- Check metadata
SELECT *
FROM rdfuser.net1#sem_model$;

-- Insert some data
INSERT INTO rdfuser.net1#rdft_m2(triple)
VALUES (SDO_RDF_TRIPLE_S('M2','<urn:person1>','<urn:name>','"John"','RDFUSER','NET1'));
COMMIT;

-- Query with SEM_MATCH
SELECT s$rdfterm, p$rdfterm, o$rdfterm
FROM TABLE(SEM_MATCH(
'SELECT ?s ?p ?o
 WHERE { ?s ?p ?o }'
,SEM_MODELS('M2')
,null,null,null,null
,' PLUS_RDFT=VC '
,null,null
,'RDFUSER','NET1'));

-- As RDFUSER, grant query only network access privileges for NET1 to RDFUSER3
CONNECT rdfuser/<password>
EXECUTE SEM_APIS.GRANT_NETWORK_ACCESS_PRIVS(network_owner=>'RDFUSER',network_name=>'NET1',network_user=>'RDFUSER3', options=>' QUERY_ONLY=T ');

-- As RDFUSER2, allow RDFUSER3 to select and query a model that RDFUSER2 owns
CONNECT rdfuser2/<password>
EXECUTE SEM_APIS.GRANT_MODEL_ACCESS_PRIVS('M2','RDFUSER3',sys.odcivarchar2list('SELECT','QUERY'),network_owner=>'RDFUSER',network_name=>'NET1');

-- As RDFUSER3, verify that model M2 is visible for querying
CONNECT rdfuser3/<password>
SELECT * 
FROM rdfuser.net1#rdf_model$ 
WHERE model_name='M2';

-- Query with SEM_MATCH
SELECT s$rdfterm, p$rdfterm, o$rdfterm
FROM TABLE(SEM_MATCH(
'SELECT ?s ?p ?o
 WHERE { ?s ?p ?o }'
,SEM_MODELS('M2')
,null,null,null,null
,' PLUS_RDFT=VC '
,null,null
,'RDFUSER','NET1'));

1.3.2 モデルのメタデータ

SEM_MODEL$ビューには、セマンティク・ネットワークで定義されているすべてのモデルに関する情報が含まれます。SEM_APIS.CREATE_SEM_MODELプロシージャを使用してモデルを作成する場合、モデルの名前と、セマンティク・データへの参照を保持する表および列を指定します。システムにより、モデルIDが自動的に生成されます。

Oracleでは、モデルを作成および削除するときにSEM_MODEL$ビューが動的に管理されます。ユーザーがこのビューを直接変更することはできません。たとえば、このビューでSQLのINSERT、UPDATEまたはDELETE文を使用することはできません。

SEM_MODEL$ビューには、表1-2に示す列が含まれます。

表1-2 SEM_MODEL$ビューの列

列名 データ型 説明

OWNER

VARCHAR2(30)

モデルの所有者のスキーマ。

MODEL_ID

NUMBER

一意のモデルID番号(自動生成)。

MODEL_NAME

VARCHAR2(25)

モデルの名前。

TABLE_NAME

VARCHAR2(30)

モデルのセマンティク・データへの参照を保持する表の名前。

COLUMN_NAME

VARCHAR2(30)

モデルのセマンティク・データへの参照を保持する表に含まれるSDO_RDF_TRIPLE_S型の列の名前。

MODEL_TABLESPACE_NAME

VARCHAR2(30)

このモデルのトリプルを格納するための表領域の名前。

MODEL_TYPE

VARCHAR2(40)

値はRDFモデルのタイプを示し、Mは通常のモデル、Vは仮想モデル、Xはセマンティク索引の内容の格納用に作成されたモデル、Dはリレーショナル・データで作成されたモデルを示します。

INMEMORY

VARCHAR2(1)

仮想モデルがOracle Database In-Memory仮想モデルかどうかを示す文字列値。In-Memoryの場合はT、In-Memoryでない場合はFです。

モデルを作成すると、そのモデルに関連付けられたトリプルのビューもネットワーク所有者のスキーマに作成されます。このビューは、SEMM_model-nameという形式の名前を持ち、モデルの所有者および適切な権限を持つユーザーにのみ表示されます。各SEMM_model-nameビューには、ネットワークにリンクとして格納されたトリプルごとに1つの行が保持されます。表1-3に、このビューの列を示します。

表1-3 SEMM_model-nameビューの列

列名 データ型 説明

P_VALUE_ID

NUMBER

トリプルの述語のテキスト値に対応するVALUE_ID。主キーの一部です。

START_NODE_ID

NUMBER

トリプルの主語のテキスト値に対応するVALUE_ID。主キーの一部です。

CANON_END_NODE_ID

NUMBER

トリプルの目的語の正規形のテキスト値に対応するVALUE_ID。主キーの一部です。

END_NODE_ID

NUMBER

トリプルの目的語のテキスト値に対応するVALUE_ID

MODEL_ID

NUMBER

トリプルが属するRDFモデルに対応するID。

COST

NUMBER

(今後使用予定)

CTXT1

NUMBER

(予約済の列。ファイングレイン・アクセス制御に使用可能)

CTXT2

VARCHAR2(4000)

(今後使用予定)

DISTANCE

NUMBER

(今後使用予定)

EXPLAIN

VARCHAR2(4000)

(今後使用予定)

PATH

VARCHAR2(4000)

(今後使用予定)

G_ID

NUMBER

トリプルのグラフ名のテキスト値に対応するVALUE_ID。Nullはデフォルト・グラフを示します(「名前付きグラフ」を参照)。

LINK_ID

VARCHAR2(71)

一意のトリプル識別子の値。(現在は計算結果列ですが、将来のリリースでは定義が変更される可能性があります。)

ノート:

表1-3の列P_VALUE_ID、START_NODE_ID、END_NODE_ID、CANON_END_NODE_IDおよびG_IDでは、実際のID値は対応する字句の値から計算されます。ただし、ある字句の値が常に同じID値にマップされるとはかぎりません。

1.3.3

RDF_VALUE$表には、RDF文を表すために使用される主語、プロパティおよび目的語に関する情報が含まれます。この表には、これらの情報の3要素に対応するテキスト値(URIまたはリテラル)が、各トリプルの要素ごとに用意された個別の行を使用して一意に格納されます。

Oracleでは、RDF_VALUE$表が自動的に管理されます。ユーザーがこのビューを直接変更することはできません。たとえば、このビューでSQLのINSERT、UPDATEまたはDELETE文を使用することはできません。

表1-4に、RDF_VALUE$表の列を示します。

表1-4 RDF_VALUE$表の列

列名 データ型 説明

VALUE_ID

NUMBER

一意の値ID番号(自動生成)。

VALUE_TYPE

VARCHAR2(10)

VALUE_NAME列に格納されたテキスト情報のタイプ。使用される値は、UR(URI)、BN(空白ノード)、PL(プレーン・リテラル)、PL@(言語タグ付きのプレーン・リテラル)、PLL(プレーン・ロング・リテラル)、PLL@(言語タグ付きのプレーン・ロング・リテラル)、TL(型付きリテラル)またはTLL(型付きロング・リテラル)です。ロング・リテラルは、4000バイトを超えるリテラルです。

VNAME_PREFIX

VARCHAR2(4000)

字句の値の長さが4000バイト以下の場合、この列に字句の値の一部である接頭辞が格納されます。接頭辞の計算には、SEM_APIS.VALUE_NAME_PREFIXファンクションを使用できます。たとえば、山カッコを除く字句<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>の一部に対応する接頭辞は、http://www.w3.org/1999/02/22-rdf-syntax-ns#です。

VNAME_SUFFIX

VARCHAR2(512)

字句の値の長さが4000バイト以下の場合、この列に字句の値の一部である接尾辞が格納されます。接尾辞の計算には、SEM_APIS.VALUE_NAME_SUFFIXファンクションを使用できます。VNAME_PREFIX列の説明に記載されている字句の値の場合、接尾辞はtypeです。

LITERAL_TYPE

VARCHAR2(4000)

型付きリテラルの場合は型情報、それ以外の場合はNULL。たとえば、1999-08-16という作成日を示す行の場合、VALUE_TYPE列にはTLが格納され、LITERAL_TYPE列にはhttp://www.w3.org/2001/XMLSchema#dateが格納されます。

LANGUAGE_TYPE

VARCHAR2(80)

言語タグ付きのリテラル(つまり、VALUE_TYPEがPL@またはPLL@の場合)の言語タグ(フランス語の場合のfrなど)。それ以外の場合、この列はNULL値です。

CANON_ID

NUMBER

現在の字句の値に対応する正規形の字句の値のID。(この列の使用は将来のリリースで変更される可能性があります。)

COLLISION_EXT

VARCHAR2(64)

字句の値の衝突処理に使用されます。(この列の使用は将来のリリースで変更される可能性があります。)

CANON_COLLISION_EXT

VARCHAR2(64)

正規形の字句の値の衝突処理に使用されます。(この列の使用は将来のリリースで変更される可能性があります。)

ORDER_TYPE

NUMBER

データ型に基づくオーダーを表します。ORDER BY問合せのパフォーマンスを向上させるために使用します。

ORDER_NUM

NUMBER

数の型に対するオーダーを表します。ORDER BY問合せのパフォーマンスを向上させるために使用します。

ORDER_DATE

TIMESTAMPWITHTIMEZONE

日付の型に基づいたオーダーを表します。ORDER BY問合せのパフォーマンスを向上させるために使用します。

LONG_VALUE

CLOB

字句の値の長さが4000バイトを超える場合の文字列。それ以外の場合、この列はNULL値です。

GEOM

SDO_GEOMETRY

空間索引が定義されている場合はジオメトリ値。

VALUE_NAME

VARCHAR2(4000)

これは計算結果列です。字句の値の長さが4000バイト以下の場合、この列の値はVNAME_PREFIX列とVNAME_SUFFIX列の値を連結したものになります。

1.3.3.1 トリプルの一意性とリテラルのデータ型

重複するトリプルはセマンティク・ネットワークに格納されません。あるトリプルが既存のトリプルと重複していないかどうかをチェックするため、新規トリプルの主語、プロパティおよび目的語は、指定したモデルのトリプル値と照合されます。新規の主語、プロパティおよび目的語がすべてURIの場合、それらの値が完全に一致した場合に重複であると判定されます。ただし、新規トリプルの目的語がリテラルの場合、主語とプロパティが完全に一致し、目的語の値が(正規化したときに)一致した場合に重複であると判定されます。たとえば、次の2つのトリプルは重複しています。

<eg:a> <eg:b> <"123"^^http://www.w3.org/2001/XMLSchema#int>
<eg:a> <eg:b> <"123"^^http://www.w3.org/2001/XMLSchema#unsignedByte>

2番目のトリプルは、1番目のトリプルの重複と判定されます。"123"^^<http://www.w3.org/2001/XMLSchema#int>には、(正規化したときに"123"^^<http://www.w3.org/2001/XMLSchema#unsignedByte>と等価の値が含まれるためです。2つのエンティティを同じ値に簡略化できる場合、それらのエンティティは正規化後に等価となります。

RDF以外の例をあげると、A*(B-C)A*B-C*A(B-C)*Aおよび-A*C+A*Bは、すべて同じ正規形に変換されます。

ノート:

重複したトリプルとクワッドはRDFM_<model>ビューの基礎となる表パーティションには格納されませんが、重複した行がアプリケーション表に含まれることはあります。たとえば、トリプルがアプリケーション表に複数回挿入された場合、RDFM_<model>ビューには1つしか表示されませんが、アプリケーション表内では複数行を占めます。

字句形式の値ベースの一致は、次のデータ型でサポートされます。

  • STRING: プレーン・リテラル、xsd:stringとその一部のXMLスキーマ・サブタイプ

  • NUMERIC: xsd:decimalとそのXMLスキーマ・サブタイプ、xsd:floatおよびxsd:double。(float/double INF、-INFおよびNaN値はサポートされません。)

  • DATETIME: タイムゾーンのサポート付きのxsd:datetime。(タイムゾーンなしの場合も、単一値に対して"2004-02-18T15:12:54""2004-02-18T15:12:54.0000"などの複数の表現が存在します。)

  • DATE: タイムゾーン付きまたはタイムゾーンなしのxsd:date

  • OTHER: その他すべて。(異なる表現を一致する試みは行われません。)

xsd:time型とxsd:dateTime型のリテラルにタイムゾーンが存在する場合、正規化が実行されます。

次の名前空間定義にはxmlns:xsd="http://www.w3.org/2001/XMLSchema"が使用されます。

RDF_VALUE$表で最初に出現するロング・リテラルは、正規形として扱われ、それぞれCPLLCPLL@またはCTLLというVALUE_TYPE値が適切に割り当てられます(つまり、正規形の場合は実際の値タイプにCという接頭辞が付けられます)。以前挿入されたロング・リテラルと同じ正規形を持つ(ただし異なる字句表現の)ロング・リテラルがRDF_VALUE$表に挿入されると、その新しい挿入に対してそれぞれPLLPLL@またはTLLというVALUE_TYPE値が適切に割り当てられます。

したがって、正規化後に等価となる異なる字句表現を持つテキスト値は、RDF_VALUE$表に格納されますが、正規化後に等価となるトリプルはデータベースに格納されません。

1.3.4 主語と目的語

RDFの主語と目的語は、セマンティク・データ・ネットワークのノードにマップされます。主語のノードはリンクの開始ノードで、目的語のノードはリンクの終了ノードです。リテラル以外のノード(URIや空白ノード)は、主語および目的語のノードとして使用できます。リテラルは、目的語のノードとしてのみ使用できます。

1.3.5 空白ノード

空白ノードは、セマンティク・ネットワークの主語および目的語のノードとして使用できます。空白ノード識別子は、1つのセマンティク・モデル内を有効範囲とする点において、URIとは異なります。つまり、単一のセマンティク・モデル内に同じ空白ノード識別子が複数出現した場合、それらは常に同じリソースを示しますが、異なる2つのセマンティク・モデル内に同じ空白ノード識別子が出現した場合、それらは同じリソースを示しません。

Oracleセマンティク・ネットワークにおいて、この動作は、空白ノードは常に1つのセマンティク・モデル内で再利用され、2つの異なるモデル間では再利用されない(つまり、同じ空白ノード識別子が使用される場合は同じリソースを表している)という要件の適用によりモデル化されます。このため、空白ノードを含むトリプルをモデルに挿入する場合、空白ノードの再利用をサポートするSDO_RDF_TRIPLE_Sコンストラクタを使用する必要があります。

1.3.6 プロパティ

プロパティは、開始ノード(主語)と終了ノード(目的語)を備えたリンクにマップされます。したがって、1つのリンクは完全なトリプルを表します。

トリプルがモデルに挿入されると、主語、プロパティおよび目的語のテキスト値について、それらがすでにデータベースに存在するかどうかがチェックされます。他のモデルの以前の文に基づくテキスト値がすでに存在する場合、新規エントリは作成されません。テキスト値が存在しない場合、RDF_VALUE$表(「文」を参照)に新規行が挿入されます。

1.3.7 推論: ルールとルールベース

推論は、ルールに基づいて論理的な推測を行う機能です。推論により、文字列などの値に基づく構文的な一致機能ではなく、データの各要素間の意味的な関係に基づいてセマンティクな一致機能を実行する問合せを作成できます。推論では、ルールベースに格納されたルールを使用し、ルールには、Oracleに付属するものとユーザーが定義するものがあります。

図1-2に、モデル・データと1つ以上のルールベースにおけるルールの適用から推論されたトリプル・セットを示します。この図の場合、データベースには任意の数のセマンティク・モデル、ルールベース、および推論されたトリプル・セットがあり、推論されたトリプル・セットは1つ以上のルールベースのルールを使用して導出されます。

ルールは、セマンティク・データから推論を導く際に適用できるオブジェクトです。ルールは、名前で識別され、次の要素で構成されます。

  • 前件に対応するIF側パターン

  • 後件に対応するTHEN側パターン

たとえば、「会議の議長は会議のレビューアでもある」というルールは、次のように表現されます。

('chairpersonRule', -- rule name
 '(?r :ChairPersonOf ?c)', -- IF side pattern
 NULL,  -- filter condition
 '(?r :ReviewerOf ?c)', -- THEN side pattern
 SEM_ALIASES (SEM_ALIAS('', 'http://some.org/test/'))
)

パフォーマンスを最大化するには、ルールのTHEN側に単一のトリプル・パターンを使用します。ルールのTHEN側に複数のトリプル・パターンが含まれる場合、THEN側でそれぞれ単一のトリプル・パターンを含むようにそれを複数のルールに簡単に分割できます。

ルールベースは、ルールを含むオブジェクトです。Oracleには、次のルールベースが付属しています。

  • RDFS

  • RDF (RDFSのサブセット)

  • OWLSIF (空)

  • RDFS++ (空)

  • OWL2EL (空)

  • OWL2RL (空)

  • OWLPrime (空)

  • SKOSCORE (空)

RDFSおよびRDFルールベースは、SEM_APIS.CREATE_SEM_NETWORKプロシージャをコールしてRDFサポートをデータベースに追加すると作成されます。RDFSルールベースでは、RDFS伴意ルールを実装します。詳細は、http://www.w3.org/TR/rdf-mt/にあるWorld Wide Web Consortium (W3C)のドキュメント 「RDF Semantics」を参照してください。RDFルールベースは、RDF伴意ルール(RDFS伴意ルールのサブセット)を表します。これらのルールベースの内容は、SEMR_RDFSおよびSEMR_RDFビューで確認できます。

SEM_APIS.CREATE_RULEBASEプロシージャを使用してユーザー定義のルールベースを作成することも可能です。ユーザー定義のルールベースを使用すると、特殊化された推論機能を追加できます。

ルールベースごとに、ルールベースのルールを保持するための表と、SEMR_rulebase-nameという形式の名前を持つビューが作成されます(たとえば、FAMILY_RBというルールベースの場合、SEMR_FAMILY_RBという名前になります)。ルールベースのルールを挿入、削除および変更するには、このビューを使用する必要があります。表1-5に、各SEMR_rulebase-nameビューの列を示します。

表1-5 SEMR_rulebase-nameビューの列

列名 データ型 説明

RULE_NAME

VARCHAR2(30)

ルールの名前

ANTECEDENTS

VARCHAR2(4000)

前件に対応するIF側パターン

FILTER

VARCHAR2(4000)

(サポートされていません。)

CONSEQUENTS

VARCHAR2(4000)

後件に対応するTHEN側パターン

ALIASES

SEM_ALIASES

使用される1つ以上の名前空間。(SEM_ALIASESデータ・タイプの説明は、「SEM_MATCHテーブル・ファンクションを使用したセマンティク・データの問合せ」を参照してください。)

すべてのルールベースに関する情報は、SEM_RULEBASE_INFOビューに保持されます。表1-6に、このビューの列を示します(1つの行が1つのルールベースに対応します)。

表1-6 SEM_RULEBASE_INFOビューの列

列名 データ型 説明:

OWNER

VARCHAR2(30)

ルールベースの所有者

RULEBASE_NAME

VARCHAR2(25)

ルールベースの名前

RULEBASE_VIEW_NAME

VARCHAR2(30)

ルールベースのルールを挿入、削除または変更する任意のSQL文で使用する必要のあるビューの名前

STATUS

VARCHAR2(30)

VALID(ルールベースが有効の場合)、INPROGRESS(ルールベースが作成中の場合)またはFAILED(ルールベースの作成中にシステム障害が発生した場合)が含まれます。

例1-3 ルールベースへのルールの挿入

例1-3では、family_rbというルールベースを作成し、そのfamily_rbルールベースにgrandparent_ruleというルールを挿入します。このルールは、ある人物がある子の親であり、その子がさらに別の子の親である場合、その人物が自分の子供の子供に対する祖父母である(つまり、自分の子供の子供に関してgrandParentOf関係を持つ)ことを示します。また、使用する名前空間も指定します。(この例は、 「例: 家系の情報」例1-122の抜粋です。)

EXECUTE SEM_APIS.CREATE_RULEBASE('family_rb', network_owner=>'RDFUSER', network_name=>'NET1');

INSERT INTO rdfuser.net1#semr_family_rb VALUES(
  'grandparent_rule',
  '(?x :parentOf ?y) (?y :parentOf ?z)',
  NULL,
  '(?x :grandParentOf ?z)', 
  SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')));

例1-3に示されている祖父母ルールのようなものは、OWL 2プロパティ・チェーン構成要素を使用して実装できることに注意してください。プロパティ・チェーンの処理の詳細は、「プロパティ・チェーンの処理」を参照してください。

例1-4 推論でのルールベースの使用

SEM_MATCH表関数(「SEM_MATCH表関数を使用したセマンティク・データの問合せ」を参照)を呼び出す場合に1つ以上のルールベースを指定することで、セマンティク・データに対する問合せの動作を制御できます。例1-4では、family_rbルールベースと、例1-3で作成したgrandParentOf関係を参照して、すべての祖父(祖父母の男性の方)とその孫を検索します。(この例は、 「例: 家系の情報」例1-122の抜粋です。)

-- Select all grandfathers and their grandchildren from the family model.
-- Use inferencing from both the RDFS and family_rb rulebases.
SELECT x$rdfterm grandfather, y$rdfterm grandchild
  FROM TABLE(SEM_MATCH(
    'PREFIX  rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
     PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
     PREFIX     : <http://www.example.org/family/>
     SELECT ?x ?y
     WHERE {?x :grandParentOf ?y . ?x rdf:type :Male}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null,  null, null,
    ' PLUS_RDFT=VC ',
    null, null,
    'RDFUSER', 'NET1'));

ネイティブOWL推論のサポートの詳細は、「OWL推論の使用方法」を参照してください。

1.3.8 伴意(ルール索引)

伴意(ルール索引)は、指定したルールベースのセットを指定したモデルのセットに適用することで推論できる計算済のトリプルを含むオブジェクトです。SEM_MATCH問合せで任意のルールベースを参照する場合、問合せ内のルールベースとモデルの組合せごとに伴意が存在している必要があります。

伴意を作成するには、SEM_APIS.CREATE_ENTAILMENTプロシージャを使用します。伴意を削除するには、SEM_APIS.DROP_ENTAILMENTプロシージャを使用します。

伴意を作成すると、その伴意に関連付けられたトリプルのビューもネットワーク所有者のスキーマに作成されます。このビューは、SEMI_entailment-nameという形式の名前を持ち、伴意の所有者および適切な権限を持つユーザーにのみ表示されます。各SEMI_entailment-nameビューには、ネットワークにリンクとして格納されたトリプルごとに1つの行が保持され、また、SEMM_model-nameビューと同じ列が含まれます(「モデルのメタデータ」表1-3を参照)。

すべての伴意に関する情報は、SEM_RULES_INDEX_INFOビューに保持されます。表1-7に、このビューの列を示します(1つの行が1つの伴意に対応します)。

表1-7 SEM_RULES_INDEX_INFOビューの列

列名 データ型 説明

OWNER

VARCHAR2(30)

伴意の所有者

INDEX_NAME

VARCHAR2(25)

伴意の名前

INDEX_VIEW_NAME

VARCHAR2(30)

伴意のルールを挿入、削除または変更する任意のSQL文で使用する必要のあるビューの名前

STATUS

VARCHAR2(30)

VALID (伴意が有効の場合)、INVALID (伴意が無効の場合)、INCOMPLETE (伴意が不完全の場合(INVALIDと似ていますが、再作成にそれほど時間がかかりません))、INPROGRESS (伴意が作成中の場合)またはFAILED (伴意の作成中にシステム障害が発生した場合)が含まれます。

MODEL_COUNT

NUMBER

伴意に含まれるモデルの数

RULEBASE_COUNT

NUMBER

伴意に含まれるルールベースの数

モデルやルールベースなど、伴意に関連するすべてのデータベース・オブジェクトの情報は、SEM_RULES_INDEX_DATASETSビューに保持されます。表1-8に、このビューの列を示します(1つの行がすべての列の値の一意の組合せに対応します)。

表1-8 SEM_RULES_INDEX_DATASETSビューの列

列名 データ型 説明

INDEX_NAME

VARCHAR2(25)

伴意の名前

DATA_TYPE

VARCHAR2(8)

伴意に含まれるデータのタイプ。たとえば、MODELおよびRULEBASEです。

DATA_NAME

VARCHAR2(25)

DATA_TYPE列に含まれるタイプのオブジェクトの名前

例1-5では、familyモデルとRDFSおよびfamily_rbルールベースを使用して、family_rb_rix_familyという伴意を作成します。(この例は、 「例: 家系の情報」例1-122の抜粋です。)

例1-5 伴意の作成

BEGIN
  SEM_APIS.CREATE_ENTAILMENT(
    'rdfs_rix_family',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    network_owner=>'RDFUSER', network_name=>'NET1');
END;
/

1.3.9 仮想モデル

仮想モデルとは、SEM_MATCH問合せで使用できる論理グラフのことです。仮想モデルは、1つ以上のモデルまたは伴意、あるいはその両方に対してUNIONまたはUNION ALL操作を実行した結果です。

仮想モデルを使用する場合の利点は次のとおりです。

  • セマンティク・データのアクセス権限の管理を簡略化できます。たとえば、3つのモデルおよびOWLPrimeルールベースに基づいて、3つのセマンティク・モデルおよび1つの伴意を作成したとします。仮想モデルを使用しない場合は、各モデルおよび伴意に対してアクセス権限の付与および取消しを個別に行う必要があります。しかし、3つのモデルと伴意を含む仮想モデルを作成すると、この1つの仮想モデルに対してのみアクセス権限の付与および取消しを行うだけで済みます。

  • セマンティク・モデルのすばやい更新を容易にできます。たとえば、仮想モデルVM1にモデルM1と伴意R1が含まれるとし(VM1 = M1 UNION ALL R1)、また、セマンティク・モデルM1_UPDは追加のトリプルで更新されたM1のコピーであり、R1_UPDはM1_UPDに作成された伴意であるとします。この場合、VM1に対するユーザー問合せで更新済のモデルおよび伴意が使用されるように、仮想モデルVM1を再定義できます(VM1 = M1_UPD UNION ALL R1_UPD)。

  • 仮想モデルへの問合せは、SEM_MATCH問合せでの複数のモデルの問合せと同等であるため、問合せの指定を簡略化できます。たとえば、モデルm1、m2およびm3がすでに存在し、OWLPrimeルールベースを使用してm1、m2およびm3に対して伴意が作成されているとします。仮想モデルvm1を次のように作成できます。

    EXECUTE sem_apis.create_virtual_model('vm1', sem_models('m1', 'm2', 'm3'), 
                                          sem_rulebases('OWLPRIME'),
                                          network_owner=>'RDFUSER',
                                          network_name=>'NET1');
    

    仮想モデルを問い合せるには、SEM_MATCH問合せのモデルと同様の仮想モデル名を使用します。たとえば、仮想モデルに対する次の問合せがあるとします。

    SELECT * FROM TABLE (sem_match('{…}', sem_models('vm1'), null, …));
    

    これは、すべての個別モデルに対する次の問合せと同等です。

    SELECT * FROM TABLE (sem_match('{…}', sem_models('m1', 'm2', 'm3'), 
                                          sem_rulebases('OWLPRIME'), …));
    

    仮想モデルに対するSEM_MATCH問合せでは、それぞれのモデルおよび伴意のUNIONまたはUNION ALLを問い合せることなく、SEMVまたはSEMUビューを問い合せます(デフォルトはSEMUで、'ALLOW_DUP=T'オプションが指定されている場合はSEMV)。これらのビューおよびオプションの詳細は、SEM_APIS.CREATE_VIRTUAL_MODELプロシージャのリファレンスの項を参照してください。

仮想モデルは、ビューを使用し(この項の後の部分を参照)、いくつかのメタデータ・エントリを追加しますが、システム記憶域要件はそれほど増大しません。

仮想モデルを作成するには、SEM_APIS.CREATE_VIRTUAL_MODELプロシージャを使用します。仮想モデルを削除するには、SEM_APIS.DROP_VIRTUAL_MODELプロシージャを使用します。仮想モデルのコンポーネント・モデル、ルールベースまたは伴意が削除されると、その仮想モデルは自動的に削除されます。それを削除することなく仮想モデルを置き換えるには、SEM_APIS.CREATE_VIRTUAL_MODELプロシージャをREPLACE=Tオプションとともに使用します。仮想モデルを置き換えると、それを再定義する一方で、任意のアクセス権限を保持することができます。

仮想モデルを問い合せるには、例1-6に示すとおり、SEM_MATCH表関数のmodelsパラメータで仮想モデル名を指定します。

SEM_MATCHテーブル・ファンクションの詳細は、「SEM_MATCHテーブル・ファンクションを使用したセマンティク・データの問合せ」を参照してください。この項には、仮想モデルを問い合せるときの特定の属性の使用方法が示されています。

仮想モデルを作成すると、SEM_MODEL$ビューに仮想モデルのエントリが作成されます(「モデルのメタデータ」表1-2を参照)。ただし、表1-9の説明にあるとおり、いくつかの列では、仮想モデルの値はセマンティク・モデルの値と異なります。

表1-9 仮想モデルのSEM_MODEL$ビューの列の説明

列名 データ型 説明

OWNER

VARCHAR2(30)

仮想モデルの所有者のスキーマ。

MODEL_ID

NUMBER

一意のモデルID番号(自動生成)。これが仮想モデルであることを表すため、負の数になります。

MODEL_NAME

VARCHAR2(25)

仮想モデルの名前。

TABLE_NAME

VARCHAR2(30)

仮想モデルの場合はNULL。

COLUMN_NAME

VARCHAR2(30)

仮想モデルの場合はNULL。

MODEL_TABLESPACE_NAME

VARCHAR2(30)

仮想モデルの場合はNULL。

すべての仮想モデルに関する情報は、SEM_VMODEL_INFOビューに保持されます。表1-10に、このビューの列を示します(1つの行が1つの仮想モデルに対応します)。

表1-10 SEM_VMODEL_INFOビューの列

列名 データ型 説明

OWNER

VARCHAR2(30)

仮想モデルの所有者。

VIRTUAL_MODEL_NAME

VARCHAR2(25)

仮想モデルの名前。

UNIQUE_VIEW_NAME

VARCHAR2(30)

仮想モデル内に一意のトリプルを含むビューの名前。ビューが作成されていない場合は、NULL。

DUPLICATE_VIEW_NAME

VARCHAR2(30)

仮想モデル内に重複するトリプル(ある場合)を含むビューの名前。

STATUS

VARCHAR2(30)

VALID(関連付けられた伴意が有効の場合)、INVALID(伴意が無効の場合)、INCOMPLETE(伴意が不完全の場合(INVALIDと似ていますが、再作成にそれほど時間がかかりません))、INPROGRESS(伴意が作成中の場合)、FAILED(伴意の作成中にシステム障害が発生した場合)、NORIDX(伴意が仮想モデルと関連付けられている場合)が含まれます。

複数の伴意がある場合は、すべてのコンポーネント伴意のうち最も低いステータスが、仮想モデルのステータスとして使用されます(INVALID < INCOMPLETE < VALID)。

MODEL_COUNT

NUMBER

仮想モデル内のモデルの数。

RULEBASE_COUNT

NUMBER

仮想モデルに使用されるルールベースの数。

RULES_INDEX_COUNT

NUMBER

仮想モデル内の伴意の数。

すべてのオブジェクト(モデル、ルールベースおよび伴意)に関する情報は、SEM_VMODEL_DATASETSビューに保持されます。表1-11に、このビューの列を示します(1つの行がすべての列の値の一意の組合せに対応します)。

表1-11 SEM_VMODEL_DATASETSビューの列

列名 データ型 説明

VIRTUAL_MODEL_NAME

VARCHAR2(25)

仮想モデルの名前。

DATA_TYPE

VARCHAR2(8)

仮想モデルに含まれるオブジェクトのタイプ。例: MODEL(セマンティク・モデル)、RULEBASE(ルールベース)、RULEIDX(伴意)。

DATA_NAME

VARCHAR2(25)

DATA_TYPE列に含まれるタイプのオブジェクトの名前

例1-6 仮想モデルの問合せ

SELECT COUNT(protein)
  FROM TABLE (SEM_MATCH (
    'SELECT ?protein
     WHERE {
      ?protein rdf:type :Protein .
      ?protein :citation ?citation . 
      ?citation :author "Bairoch A."}',
    SEM_MODELS('UNIPROT_VM'), 
    NULL, 
    SEM_ALIASES(SEM_ALIAS('', 'http://purl.uniprot.org/core/')),
    NULL, 
    NULL, 
    'ALLOW_DUP=T',
    NULL,
    NULL,
    'RDFUSER','NET1'));

1.3.10 名前付きグラフ

RDFセマンティク・グラフは名前付きグラフの使用をサポートしており、これについてはW3C勧告の「SPARQL Query Language for RDF」のRDFデータセットに関する項(http://www.w3.org/TR/rdf-sparql-query/#rdfDataset)で説明されています。

このサポートは、従来の主語、述語、目的語で構成されるRDFトリプルを、グラフ名を表す追加の構成要素を含めるように拡張することで実現されます。拡張されたRDFトリプルは、4つの構成要素を含みますが、このドキュメントでは引き続きRDFトリプルと呼びます。また、次の用語が使用されることもあります。

  • N-Triple: 拡張トリプルを許可しない形式です。したがって、n-tripleは3つのコンポーネントを持つトリプルのみを含むことができます。

  • N-Quad: 通常のトリプル(3つのコンポーネント)と拡張トリプル(グラフ名を含む4つのコンポーネント)を許可する形式です。詳細は、http://www.w3.org/TR/2013/NOTE-n-quads-20130409/を参照してください。

    拡張トリプルを含むファイル(通常は標準トリプルが混在)をOracle Databaseにロードする場合、入力ファイルはN-Quad形式である必要があります。

RDFトリプルのグラフ名の構成要素は、NULLまたはURIである必要があります。これがNULLの場合、RDFトリプルはデフォルト・グラフに属していると言われます(それ以外の場合、URIで指定された名前を持つ名前付きグラフに属していると言われます)。

また、SDO_RDF_TRIPLE_Sオブジェクト型(「セマンティク・データの型、コンストラクタ、およびメソッド」を参照)の名前付きグラフをサポートするため、モデル-グラフ(モデルとグラフ(存在する場合)の組合せ)を指定するための新しい構文が用意され、RDF_M_ID属性はモデル-グラフの識別子(グラフ(存在する場合)のモデルIDと値IDの組合せ)を保持します。モデル-グラフの名前をmodel_nameとして指定し、グラフが存在する場合は、その後にコロン(:)区切り文字とグラフ名が続きます(これはURIであり、山カッコ< >で囲まれる必要があります)。

たとえば、医療データセットでは、各RDFトリプルの名前付きグラフの構成要素は患者の識別子に基づくURIになるため、一意の患者と同じ数の名前付きグラフが存在することになります(それぞれの名前付きグラフは特定の患者のデータで構成されます)。

名前付きグラフに特定の操作を実行する方法の詳細は、次の項を参照してください。

1.3.10.1 名前付きグラフ・サポートに関連したデータ形式

TriGおよびN-QUADSの2つは、グラフ名(またはコンテキスト)をトリプル・データに与えるための一般的なデータ形式です。グラフ名(コンテキスト)は様々な方法で使用できます。典型的な使用方法には、管理、ローカライズされた問合せ、ローカライズされた推論および来歴を容易にするためのトリプルのグループ化がありますが、これに限定されるものではありません。

例1-7 TriG形式でエンコードされたRDFデータ

例1-7は、TriG形式でエンコードされるRDFデータセットを示しています。デフォルト・グラフと名前付きグラフが含まれます。

@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .
 
# Default graph
{
  <http://my.com/John> dc:publisher <http://publisher/Xyz> .
}
 
# A named graph
<http://my.com/John> {
  <http://my.com/John> foaf:name "John Doe" .
}

例1-7のTriGファイルをDatasetGraphOracleSemオブジェクトにロード(たとえば、RDF Semantic Graph Support for Apache Jenaを使用したバルク・ロード例7-12を使用)する場合に、定数"N-QUADS""TRIG"に置き換えると、デフォルト・グラフ内のトリプルは、トリプルとしてnullのグラフ名とともにOracle Databaseにロードされ、名前付きグラフ内のトリプルは指定されたグラフ名とともにOracle Databaseにロードされます。

例1-8 N-QUADS形式の表現

N-QUADS形式は、オプションの4番目の列(グラフ名またはコンテキスト)を追加することで既存のN-TRIPLES形式を単純に拡張したものです。例1-8に、例1-7に基づくTriGファイルのN-QUADS形式の表現を示します。

<http://my.com/John> <http://purl.org/dc/elements/1.1/publisher> <http://publisher/Xyz> .
<http://my.com/John> <http://xmlns.com/foaf/0.1/name> "John Doe" <http://my.com/John>

N-QUADSファイルをDatasetGraphOracleSemオブジェクトにロードすると(例7-12を参照)、4つ目の列のない行はnullグラフ名を持つトリプルとしてOracle Databaseにロードされ、4つ目の列がある行は指定されたグラフ名でOracle Databaseにロードされます。

1.3.11 セマンティク・データのセキュリティ上の考慮事項

セマンティク・データを使用する場合、次のデータベース・セキュリティの考慮事項が適用されます。

  • モデルまたは伴意を作成すると、関連ビューに対するGRANTオプション付きのSELECT権限が所有者に付与されます。これらのビューに対してSELECT権限を持つユーザーは、関連モデルまたは伴意に対してSEM_MATCH問合せを実行できます。

  • ルールベースを作成すると、ルールベースに対するGRANTオプション付きのSELECT、INSERT、UPDATEおよびDELETE権限が所有者に付与されます。ルールベースに対してSELECT権限を持つユーザーは、ルールベースを含む伴意を作成できます。INSERT、UPDATEおよびDELETE権限により、ルールベースを変更できるユーザーと、その変更方法が制御されます。

  • モデルに対してデータ操作言語(DML)の操作を実行する場合、ユーザーは対応する実表に対するDML権限を持っている必要があります。

  • モデルに対応する実表の作成者は、他のユーザーに権限を付与できます。

  • ルールベースに対してデータ操作言語(DML)の操作を実行する場合、ユーザーは対応するデータベース・ビューに対する適切な権限を持っている必要があります。

  • モデルの作成者は、対応するデータベース・ビューに対するSELECT権限を他のユーザーに付与できます。

  • ユーザーは、対応するデータベース・ビューに対するSELECT権限を持っているモデルのみを問い合せることができます。

  • モデルまたはルールベースを削除できるのは、その作成者のみです。

1.3.12 RDFの権限に関する考慮事項

セマンティク・ネットワークを使用する場合は、データベース権限に関して次の考慮事項があります。

  • リリース12.2では、セマンティク・ネットワークの作成などの管理プロシージャをSYSTEMとして(またはDBAロールを持つ別の非SYSユーザーとして)実行する必要があります。MDSYSにINHERIT ANY PRIVILEGES権限がなくなったため、これらのプロシージャをSYSとして実行することはできません。

  • リリース18では、MDSYSユーザーにUNLIMITED TABLESPACE権限がなくなったため、MDSYS所有セマンティク・ネットワークで使用する表領域の割当て制限をMDSYSに明示的に付与する必要があります。

1.4 セマンティク・メタデータ表およびビュー

Oracle Databaseでは、セマンティク・データに関連するメタデータを保持するために、ネットワーク所有者のスキーマで複数の表およびビューが管理されます。

これらの表およびビューの一部は、「セマンティク・データを使用するためのクイック・スタート」に記載されているSEM_APIS.CREATE_SEM_NETWORKプロシージャによって作成され、一部は必要な場合にのみ作成されます。表1-12に、そうした表とビューの一覧をアルファベット順に示します。(さらに、いくつかの表およびビューはOracle内部使用のために作成され、DBA権限を持つユーザーまたはスキーマプライベート・セマンティク・ネットワークのネットワーク所有者のみがアクセスできます。)

表1-12 セマンティク・メタデータ表およびビュー

名前 含まれる情報 参照先

RDF_CRS_URI$

利用可能なEPSG空間参照システムURI

空間のサポート

RDF_VALUE$

文を表すのに使用される主語、プロパティおよび目的語

SEM_DTYPE_INDEX_INFO

ネットワークのすべてのデータ型索引

データ型索引の使用

SEM_MODEL$

データベースに定義されているすべてのモデル

モデルのメタデータ

SEM_NETWORK_INDEX_INFO$

セマンティク・ネットワーク索引

MDSYS.SEM_NETWORK_INDEX_INFOビュー

SEM_RULEBASE_INFO

ルールベース

推論: ルールとルールベース

SEM_RULES_INDEX_DATASETS

伴意で使用されるデータベース・オブジェクト

伴意(ルール索引)

SEM_RULES_INDEX_INFO

伴意(ルール索引)

伴意(ルール索引)

SEM_VMODEL_INFO

仮想モデル

仮想モデル

SEM_VMODEL_DATASETS

仮想モデルで使用されるデータベース・オブジェクト

仮想モデル

SEMCL_entailment-name

owl:sameAsクリーク・メンバーと正規形の代表

owl:sameAs推論の最適化

SEMI_entailment-name

指定した伴意のトリプル

伴意(ルール索引)

SEMM_model-name

指定したモデルのトリプル

モデルのメタデータ

SEMR_rulebase-name

指定したルールベースのルール

推論: ルールとルールベース

SEMU_virtual-model-name

仮想モデル内の一意のトリプル

仮想モデル

SEMV_virtual-model-name

仮想モデル内のトリプル

仮想モデル

1.5 セマンティク・データの型、コンストラクタおよびメソッド

SDO_RDF_TRIPLE_Sオブジェクト型は、RDFグラフのエッジ(つまり、トリプルとクワッド)を表すために使用されます。

SDO_RDF_TRIPLE_Sオブジェクト型(_Sはストレージ)は、データベースに永続的なセマンティク・データを格納します。

実際のセマンティク・データはRDFスキーマにのみ一元的に格納されるため、SDO_RDF_TRIPLE_S型はデータに対する参照を保持します。この型には、トリプルの一部または全部を取得するためのメソッドがあります。

ノート:

空白ノードは、常に1つのRDFモデル内で再利用されます。複数のモデル間で再利用することはできません。

SDO_RDF_TRIPLE_S型は、トリプルをデータベース表に格納するために使用されます。

SDO_RDF_TRIPLE_Sオブジェクト型には、次の属性が含まれます。

SDO_RDF_TRIPLE_S (
  RDF_C_ID NUMBER, -- Canonical object value ID
  RDF_M_ID NUMBER, -- Model (or Model-Graph) ID 
  RDF_S_ID NUMBER, -- Subject value ID
  RDF_P_ID NUMBER, -- Property value ID
  RDF_O_ID NUMBER) -- Object value ID

SDO_RDF_TRIPLE_S型には、RDFモデル(またはモデル-グラフ)の名前、またはトリプルの一部(主語、プロパティまたは目的語)を取得する次のメソッドがあります。

GET_MODEL(
 NETWORK_OWNER VARCHAR2 DEFAULT NULL,
 NETWORK_NAME  VARCHAR2 DEFAULT NULL) RETURNS VARCHAR2
GET_SUBJECT(
 NETWORK_OWNER VARCHAR2 DEFAULT NULL,
 NETWORK_NAME  VARCHAR2 DEFAULT NULL) RETURNS VARCHAR2
GET_PROPERTY(
 NETWORK_OWNER VARCHAR2 DEFAULT NULL,
 NETWORK_NAME  VARCHAR2 DEFAULT NULL) RETURNS VARCHAR2
GET_OBJECT(
 NETWORK_OWNER VARCHAR2 DEFAULT NULL,
 NETWORK_NAME  VARCHAR2 DEFAULT NULL) RETURNS CLOB
GET_OBJ_VALUE(
 NETWORK_OWNER VARCHAR2 DEFAULT NULL,
 NETWORK_NAME VARCHAR2 DEFAULT NULL) RETURNS VARCHAR2

例1-9に、SDO_RDF_TRIPLE_Sのメソッドをいくつか示します。

例1-9 SDO_RDF_TRIPLE_Sのメソッド

-- Find all articles that reference Article2.
SELECT a.triple.GET_SUBJECT('RDFUSER','NET1') AS subject
    FROM RDFUSER.NET1#RDFT_ARTICLES a
    WHERE a.triple.GET_PROPERTY('RDFUSER','NET1') = '<http://purl.org/dc/terms/references>' 
    AND a.triple.GET_OBJ_VALUE('RDFUSER','NET1') = '<http://nature.example.com/Article2>';

SUBJECT                                                                         
--------------------------------------------------------------------------------
<http://nature.example.com/Article1>                                            

-- Find all triples with Article1 as subject.
SELECT a.triple.GET_SUBJECT('RDFUSER','NET1') AS subject, 
       a.triple.GET_PROPERTY('RDFUSER','NET1') AS property, 
       a.triple.GET_OBJ_VALUE('RDFUSER','NET1') AS object
    FROM RDFUSER.NET1#RDFT_ARTICLES a
    WHERE a.triple.GET_SUBJECT('RDFUSER','NET1') = '<http://nature.example.com/Article1>';

SUBJECT
--------------------------------------------------------------------------------
PROPERTY
--------------------------------------------------------------------------------
OBJECT
--------------------------------------------------------------------------------
<http://nature.example.com/Article1>
<http://purl.org/dc/elements/1.1/title>
"All about XYZ"

<http://nature.example.com/Article1>
<http://purl.org/dc/elements/1.1/creator>
"Jane Smith"

<http://nature.example.com/Article1>
<http://purl.org/dc/terms/references>
<http://nature.example.com/Article2>

<http://nature.example.com/Article1>
<http://purl.org/dc/terms/references>
<http://nature.example.com/Article3
                                                                                
-- Find all objects where the subject is Article1.
SELECT a.triple.GET_OBJ_VALUE('RDFUSER','NET1') AS object
    FROM RDFUSER.NET1#RDFT_ARTICLES a
    WHERE a.triple.GET_SUBJECT('RDFUSER','NET1') = '<http://nature.example.com/Article1>';

OBJECT                                                                          
--------------------------------------------------------------------------------
"All about XYZ"                                                                 
"Jane Smith"                                                                    
<http://nature.example.com/Article2>                                            
<http://nature.example.com/Article3>                                            

-- Find all triples where Jane Smith is the object.
SELECT a.triple.GET_SUBJECT('RDFUSER','NET1') AS subject,
       a.triple.GET_PROPERTY('RDFUSER','NET1') AS property, 
       a.triple.GET_OBJ_VALUE('RDFUSER','NET1') AS object
    FROM RDFUSER.NET1#RDFT_ARTICLES a
    WHERE a.triple.GET_OBJ_VALUE('RDFUSER','NET1') = '"Jane Smith"';

SUBJECT
--------------------------------------------------------------------------------
PROPERTY
--------------------------------------------------------------------------------
OBJECT
--------------------------------------------------------------------------------
<http://nature.example.com/Article1>
<http://purl.org/dc/elements/1.1/creator>
"Jane Smith"

1.5.1 トリプルを挿入するためのコンストラクタ

次のコンストラクタ書式は、トリプルをモデル表に挿入する場合に使用できます。2つの書式の唯一の違いは、2番目の書式における目的語のデータ型がCLOBであり、非常に長いリテラルに対応できることです。

SDO_RDF_TRIPLE_S (
  model_name    VARCHAR2, -- Model name
  subject       VARCHAR2, -- Subject
  property      VARCHAR2, -- Property
  object        VARCHAR2, -- Object
  network_owner VARCHAR2 DEFAULT NULL,
  network_name  VARCHAR2 DEFAULT NULL) 
  RETURN     SELF;

SDO_RDF_TRIPLE_S (
  model_name    VARCHAR2, -- Model name
  subject       VARCHAR2, -- Subject
  property      VARCHAR2, -- Property
  object        CLOB,     -- Object
  network_owner VARCHAR2 DEFAULT NULL,
  network_name  VARCHAR2 DEFAULT NULL)
  RETURN SELF;

例1-10では、1番目のコンストラクタ書式を使用して複数のトリプルを挿入します。

例1-10 トリプルを挿入するSDO_RDF_TRIPLE_Sコンストラクタ

INSERT INTO RDFUSER.NET1#RDFT_ARTICLES VALUES (
  SDO_RDF_TRIPLE_S ('articles','<http://nature.example.com/Article1>',
    '<http://purl.org/dc/elements/1.1/creator>',
    '"Jane Smith"',
    'RDFUSER',
    'NET1'));

INSERT INTO RDFUSER.NET1#RDFT_ARTICLES VALUES (
  SDO_RDF_TRIPLE_S ('articles:<http://examples.com/ns#Graph1>',
    '<http://nature.example.com/Article102>',
    '<http://purl.org/dc/elements/1.1/creator>',
    '_:b1',
    'RDFUSER',
    'NET1'));
 
INSERT INTO RDFUSER.NET1#RDFT_ARTICLES VALUES (
  SDO_RDF_TRIPLE_S ('articles:<http://examples.com/ns#Graph1>',
    '_:b2',
    '<http://purl.org/dc/elements/1.1/creator>',
    '_:b1',
    'RDFUSER',
    'NET1'));

1.6 SEM_MATCH表関数を使用したセマンティク・データの問合せ

セマンティク・データを問い合せるには、SEM_MATCH表関数を使用します。

ノート:

共有デプロイメントでAutonomous Databaseインスタンスを使用している場合、SEM_MATCH表関数には、Oracle JVMの有効化が必要です。Autonomous DatabaseインスタンスでOracle JVMを有効にするには、共有ExadataインフラストラクチャでのOracle Autonomous Databaseの使用Oracle Javaの使用を参照してください。

この関数には、次の属性が含まれます。

SEM_MATCH(
  query         VARCHAR2,
  models        SEM_MODELS,
  rulebases     SEM_RULEBASES,
  aliases       SEM_ALIASES,
  filter        VARCHAR2,
  index_status  VARCHAR2    DEFAULT NULL,
  options       VARCHAR2    DEFAULT NULL,
  graphs        SEM_GRAPHS  DEFAULT NULL,
  named_graphs  SEM_GRAPHS  DEFAULT NULL,
  network_owner VARCHAR2    DEFAULT NULL,
  network_name  VARCHAR2    DEFAULT NULL
 ) RETURN ANYDATASET;

queryおよびmodels属性は必須です。その他の属性はオプションです(それぞれNULL値を指定できます)。

query属性は、通常は変数が含まれる1つ以上のトリプル・パターンを備えた文字列リテラル(または文字列リテラルを連結したもの)です。(query属性には、バインド変数またはバインド変数を含む式を指定することはできません。)トリプル・パターンは、ピリオドで囲まれた3つのアトムです。各アトムには、変数(?xなど)、デフォルトの名前空間およびaliases属性の値に基づいて拡張された修飾名(rdf:type)、または完全なURI (<http://www.example.org/family/Male>など)を指定できます。また、3番目のアトムには、数値リテラル(3.14など)、プレーン・リテラル("Herman"など)、言語タグ付きのプレーン・リテラル("Herman"@enなど)または型付きリテラル("123"^^xsd:intなど)を指定できます。

たとえば、次のquery属性では、3つのトリプル・パターンを使用して祖父(祖父母の男性の方)とその孫の身長を検索します。

'SELECT * WHERE { ?x :grandParentOf ?y . ?x rdf:type :Male . ?y :height ?h }'

models属性では、使用する1つ以上のモデルを指定します。そのデータ型は、TABLE OF VARCHAR2(25)という定義を持つSEM_MODELSです。仮想モデルを問い合せる場合、他のモデル名は指定せず、その仮想モデルの名前のみを指定します。(仮想モデルの詳細は、「仮想モデル」を参照してください。)

rulebases属性では、問合せに適用するルールが含まれる1つ以上のルールベースを指定します。そのデータ型は、TABLE OF VARCHAR2(25)という定義を持つSDO_RDF_RULEBASESです。仮想モデルを問い合せる場合、この属性はNULLである必要があります。

aliases属性では、デフォルトの名前空間以外に、問合せパターンの修飾名の拡張に使用する1つ以上の名前空間を指定します。そのデータ型は、TABLE OF SEM_ALIASという定義を持つSEM_ALIASESです。各SEM_ALIAS要素により、名前空間IDと名前空間値が識別されます。SEM_ALIASデータ型は、(namespace_id VARCHAR2(30), namespace_val VARCHAR2(4000))という定義を持ちます。

SEM_MATCH表関数とSEM_CONTAINSおよびSEM_RELATED演算子では、次のデフォルトの名前空間(namespace_id属性とnamespace_val属性)が使用されます。

('ogc', 'http://www.opengis.net/ont/geosparql#')
('ogcf', 'http://www.opengis.net/def/function/geosparql/')
('ogcgml', 'http://www.opengis.net/ont/gml#')
('ogcsf', 'http://www.opengis.net/ont/sf#')
('orardf', 'http://xmlns.oracle.com/rdf/')
('orageo', 'http://xmlns.oracle.com/rdf/geo/')
('owl',    'http://www.w3.org/2002/07/owl#')
('rdf',    'http://www.w3.org/1999/02/22-rdf-syntax-ns#')
('rdfs',   'http://www.w3.org/2000/01/rdf-schema#')
('xsd',    'http://www.w3.org/2001/XMLSchema#')

これらのデフォルトを上書きするには、aliases属性でnamespace_id値および異なるnamespace_val値を指定します。

filter属性では、追加の選択基準を指定します。この属性がNULLではない場合、WHEREキーワードのないWHERE句の形式で文字列を指定する必要があります。たとえば、この項で前に示したトリプル・パターンの例で'(h >= ''6'')'と指定すると、身長が6以上である祖父の孫に検索結果を絞り込めます。

ノート:

filter属性を使用するかわりに、できるかぎり問合せパターン内でFILTERキーワードを使用してください(「グラフ・パターン: 中カッコの構文とOPTIONAL、FILTER、UNIONおよびGRAPHキーワードのサポート」を参照)。FILTERキーワードを使用すると、内部が最適化されるため、パフォーマンスが向上する傾向があります。ただし、FILTERキーワードで表現できないSQL構成要素が必要な場合は、filter引数が便利です。

index_status属性では、関連する伴意のステータスが無効の場合でも、セマンティク・データを問い合せることができます。(仮想モデルを問い合せる場合、この属性は、その仮想モデルに関連付けられた伴意を参照します。)この属性がnullの場合、伴意のステータスが無効だと、問合せによりエラーが戻されます。この属性がNULLではない場合、文字列INCOMPLETEまたはINVALIDを指定する必要があります。異なるindex_status値を持つ問合せの動作については、「不完全な伴意または無効な伴意を使用した問合せの実行」の説明を参照してください。

options属性は、問合せの結果に影響を与えることのできるオプションを指定します。オプションは、キーワードと値のペアで表記します。次のオプションがサポートされています。

  • ALL_AJ_HASHALL_AJ_MERGEおよびALL_BGP_NLは、グローバル問合せオプティマイザ・ヒントです。これにより、指定された結合タイプが、NOT EXISTS演算子およびMINUS演算子に対するすべての反結合で使用されることになります。

  • ALL_BGP_HASHおよびALL_BGP_NLは、すべてのBGP間の結合(ルートBGPとOPTIONAL BGPの間の結合など)で指定の結合タイプを使用する必要があることを示すグローバル問合せオプティマイザ・ヒントです。(BGPは、basic graph patternの略語です)。W3C勧告の「SPARQL Query Language for RDF」の説明では、「SPARQLのグラフ・パターン照合は、基本グラフ・パターンの照合結果を組み合せるという観点で定義されています。単一の基本グラフ・パターンは、フィルタの割込がある一連のトリプル・パターンによって形成されます。任意のグラフ・パターンによって、基本グラフ・パターンが終了します」と記述されています。

    BGP_JOIN(USE_NL)およびBGP_JOIN(USE_HASH) HINT0問合せオプティマイザ・ヒントを使用して、結合タイプをきめ細かく制御できます。

    例1-17に、SEM_MATCH問合せで使用されるALL_BGP_HASHオプションを示します。

  • ALL_LINK_HASHおよびALL_LINK_NLは、すべてのRDF_LINK$結合(BGP内のトリプル・パターン間のすべての結合)の結合タイプを指定するグローバル問合せオプティマイザ・ヒントです。ALL_LINK_HASHALL_LINK_NLも、きめ細かい制御のためにHINT0問合せオプティマイザ内で使用できます。

  • ALL_MAX_PP_DEPTH(n)はグローバル問合せオプティマイザ・ヒントです。これは、プロパティ・パス演算子*と+の評価に使用する最大深度を設定します。デフォルト値は10です。MAX_PP_DEPTH(n) HINT0ヒントは、さらに細かく最大深度を指定するために使用できます。

  • ALL_ORDEREDは、問合せ内の各BGPのトリプル・パターンが順番に評価される必要があることを指定するグローバル問合せオプティマイザ・ヒントです。

    例1-17に、SEM_MATCH問合せで使用されるALL_ORDEREDオプションを示します。

  • ALL_USE_PP_HASHおよびALL_USE_PP_NLは、プロパティ・パス表現の評価に使用する結合タイプを指定するグローバル問合せオプティマイザ・ヒントです。USE_PP_HASHおよびUSE_PP_NL HINT0ヒントは、結合タイプをさらにきめ細かく指定するために使用できます。

  • ALLOW_DUP=Tは、セマンティク・モデルと推論データ(適用可能な場合)のUNIONではなくUNION ALLを実行する、基礎となるSQL文を生成します。このオプションを使用した場合、結果セットに追加の行(重複するトリプル)が生成されるために、それに応じてアプリケーション・ロジックを調整する必要があることがあります。このオプションを指定しない場合、すべてのモデルと推論データにわたって、重複するトリプルは自動的に削除され、マージされたRDFグラフの設定済セマンティクが保持されます。ただし、重複するトリプルを削除すると、問合せの処理時間が長くなります。一般に、1つのSEM_MATCH問合せに複数のセマンティク・モデルが関連している場合、'ALLOW_DUP=T'を指定することで、パフォーマンスが大幅に向上します。

    仮想モデルを問い合せる場合、ALLOW_DUP=Tを指定すると、SEMV_vm_nameビューが問い合せられます。指定しない場合、SEMU_vm_nameビューが問い合せられます。

  • ALLOW_PP_DUP=Tは、+および*プロパティ・パス問合せで結果の重複を許可します。結果の重複が認められると、最初の結果行が早く戻されます。

  • AS_OF [SCN, <SCN_VALUE>]は、指定したSCN時点におけるセマンティク・ネットワークの状態の問合せに、フラッシュバック問合せ使用しなければならないことを示すものです。ここで、<SCN_VALUE>は、有効なシステム変更番号です。

  • AS_OF [TIMESTAMP, <TIMESTAMP_VALUE>]は、指定したタイムスタンプ時点におけるセマンティク・ネットワークの状態の問合せに、フラッシュバック問合せ使用しなければならないことを示すものです。ここで、<TIMESTAMP_VALUE>は、「YYYY/MM/DD HH24:MI:SS.FF」の形式を持つ有効なタイムスタンプ文字列です。

  • CLOB_AGG_SUPPORT=Tは、集計(MIN、MAX、GROUP_CONCAT、SAMPLE)でCLOB値のサポートを有効にします。CLOBサポートを有効化するとパフォーマンスが大幅に低下することに注意してください。

  • CLOB_EXP_SUPPORT=Tは、一部の組込みSPARQL関数でのCLOB値のサポートを有効にします。CLOBサポートを有効化するとパフォーマンスが大幅に低下することに注意してください。

  • CONSTRUCT_STRICT=Tは、SPARQL CONSTRUCTまたはSPARQL DESCRIBE構文の問合せの結果から無効なRDFトリプルを消去します。主語の位置にリテラルがあるRDFトリプル、または述語の位置にリテラルか空白ノードがあるRDFトリプルは無効とみなされます。

  • CONSTRUCT_UNIQUE=Tは、SPARQL CONSTRUCTまたはSPARQL DESCRIBE構文の問合せの結果から重複RDFトリプルを消去します。

  • DISABLE_IM_VIRTUAL_COLは、問合せコンパイラがインメモリー仮想列を使用しないことを指定します。

  • DISABLE_NULL_EXPR_JOINは、すべてのSELECT式について、NULLでない出力を生成するものとして処理するよう、コンパイラに対し指定するものです。

  • DISABLE_SAMEAS_BLOOMは、owl:sameAsトリプルが結合されている場合に問合せコンパイラがブルーム・フィルタを使用しないことを指定します。(詳細は、『Oracle Database SQLチューニング・ガイド』のブルーム・フィルタの説明を参照してください。)

  • DO_UNESCAPE=Tは、返却列のvar、var$_PREFIX、var$_SUFFIX、var$RDFCLOB、var$RDFLTYP、var$RDFLANGおよびvar$RDFTERMの文字を、W3CのN-Triples仕様(http://www.w3.org/TR/rdf-testcases/#ntriples)に従ってエスケープしません。

    SEM_APIS.ESCAPE_CLOB_TERMSEM_APIS.ESCAPE_CLOB_VALUESEM_APIS.ESCAPE_RDF_TERMSEM_APIS.ESCAPE_RDF_VALUESEM_APIS.UNESCAPE_CLOB_TERMSEM_APIS.UNESCAPE_CLOB_VALUESEM_APIS.UNESCAPE_RDF_TERMおよびSEM_APIS.UNESCAPE_RDF_VALUEのリファレンス情報も参照してください。

  • FINAL_VALUE_HASHおよびFINAL_VALUE_NLは、FILTER句で使用されていない問合せ変数の字句の値を取得するために、使用する必要がある結合メソッドを指定するグローバル問合せオプティマイザ・ヒントです。

  • GRAPH_MATCH_UNNAMED=Tを使用すると、名前なしトリプル(null G_ID)をGRAPH句内で照合可能になります。つまり、グラフが等しい場合、またはグラフの一方または両方がnullの場合、2つのトリプルはグラフ結合条件を満たすことになります。データセットに名前なしTBOXトリプルまたは名前なし伴意トリプルが含まれている場合に、このオプションが役立つことがあります。

  • HINT0={<hint-string>}(発音および表記は"hint (ヒント)"と数字のゼロ)は、1つ以上のキーワードを、問合せの実行計画および結果に影響を与えるヒントとともに指定します。概念的には、n個のトリプル・パターンを持つグラフ・パターンで、m個の固有の変数を参照した場合、(n+m)方向の結合となります。つまり、ターゲットRDFモデルおよび対応する伴意(オプション)のn方向の自己結合が実行された後、値からm個の変数を検索するために、RDF_VALUE$でm個の結合が実行されます。ヒント指定は、問合せ実行で使用される結合順序と結合タイプに影響を与えます。

    ヒント指定<hint-string>では、キーワードを使用します。一部のキーワードは、問合せで使用される各トリプル・パターンおよび変数ごとに、一連(一群)の別名または参照で構成されるパラメータを持ちます。トリプル・パターンの別名の形式は、tiです。iは、問合せ内のトリプル・パターンの0から始まる序数です。たとえば、問合せ内の最初のトリプル・パターンの別名はt0で、2番目のトリプル・パターンの別名はt1、...のようになります。問合せで使用される変数の別名は単に、その変数の名前です。このため、ヒント指定では、グラフ・パターンで使用される変数?xの別名として?xが使用されます。

    問合せの実行計画に影響を与えるために使用するヒントには、LEADING(<sequence of aliases>)、USE_NL(<set of aliases>)、USE_HASH(<set of aliases>)およびINDEX(<alias> <index_name>)があります。これらのヒントの書式と基本的な意味は、SQL文のヒントと同じです(『Oracle Database SQL言語リファレンス』を参照)。

    例1-12に、SEM_MATCH問合せで使用されるHINT0オプションを示します。

  • HTTP_METHOD=POST_PARは、URLエンコーディング・パラメータ・パスを含むHTTP POSTメソッドをSERVICEリクエストに対して使用する必要があると指定します。リクエストのデフォルト・オプションはHTTP GETメソッドです。SPARQLプロトコルの詳細は、http://www.w3.org/TR/2013/REC-sparql11-protocol-20130321/#protocolを参照してください。

  • INF_ONLY=Tは、指定されたモデルおよびルールベースの伴意グラフのみを問い合せます。

  • OVERLOADED_NL=Tは、過負荷のSERVICE句に対し、ネストした手続き型ループによる実行が必要であることを指定するものです。

  • PLUS_RDFT=Tは、SPARQL SELECT構文(「SELECT句の式」を参照)で、射影される各問合せ変数のvar$RDFTERM CLOB列を追加で返す場合に使用できます。この列の値は、SEM_APIS.COMPOSE_RDF_TERM(var, var$RDFVTYP, var$RDFLTYP, var$RDFLANG, var$RDFCLOB)の結果と同等です。このオプションを使用する場合、各変数varの戻り列は、varvar$RDFVID、var$_PREFIX、var$_SUFFIX、var$RDFVTYP、var$RDFCLOB、var$RDFLTYP、var$RDFLANGおよびvar$RDFTERMになります。

  • PLUS_RDFT=VCは、SPARQL SELECT構文(「SELECT句の式」を参照)で、射影される各問合せ変数のvar$RDFTERM VARCHAR2(4000)列を追加で返す場合に使用できます。この列の値は、SEM_APIS.COMPOSE_RDF_TERM(var, var$RDFVTYP, var$RDFLTYP, var$RDFLANG)の結果と同等です。このオプションを使用する場合、各変数varの戻り列は、var、var$RDFVID、var$_PREFIX、var$_SUFFIX、var$RDFVTYP、var$RDFCLOB、var$RDFLTYP、var$RDFLANGおよびvar$RDFTERMになります。

  • PROJ_EXACT_VALUES=Tは、関数から返される値と、値割当て文で使用される定数値の正規化を無効にします。これらの値はデフォルトでは正規化されます。

  • SERVICE_CLOB=Fは、サービスをコールするときにvar$RDFCLOBの列値を保存するかわりに値にnullを設定します。CLOBデータがアプリケーションで必要ない場合、このオプションを使用してCLOB処理を省略するとパフォーマンスを向上させることができます。

  • SERVICE_ESCAPE=Fは、SPARQL SERVICEコールから返されるRDFリテラル値の文字のエスケープを無効にします。RDFリテラル値はデフォルトではエスケープされます。文字のエスケープがアプリケーションに関係ない場合は、文字のエスケープを無効にするとパフォーマンスを向上させることができます。

  • SERVICE_JPDWN=Tは、SPARQL SERVICEでネステッド・ループ結合を使用するための問合せオプティマイザ・ヒントです。例1-73に、SEM_MATCH問合せで使用されるSERVICE_JPDWN=Tオプションを示します。

  • SERVICE_PROXY=<proxy-string>は、http接続を実行するときに使用されるプロキシ・アドレスを設定します。指定したproxy-stringがSERVICE問合せで使用されます。例1-76に、プロキシ・アドレスを含むSEM_MATCH問合せを示します。

  • STRICT_AGG_CARD=Tは、一致しなかったグラフ・パターンを含む集計問合せで、SPARQLセマンティク(1つのnull行)をSQLセマンティク(0行)のかわりに使用します。このオプションによってパフォーマンスがわずかに低下します。

  • STRICT_DEFAULT=Tは、データセット情報が指定されない場合に、デフォルト・グラフを名前なしトリプルに制限します。

graphs属性は、SEM_MACH問合せ用のデフォルト・グラフの構築元となる、名前付きグラフのセットを指定します。そのデータ型はSEM_GRAPHSで、TABLE OF VARCHAR2(4000)という定義を持ちます。この属性のデフォルト値はNULLです。graphsNULLの場合、問合せモデルのセット内のすべてのグラフのすべての和集合が、デフォルト・グラフとして使用されます。

named_graphs属性は、GRAPH句で照合可能な名前付きグラフのセットを指定します。そのデータ型はSEM_GRAPHSで、TABLE OF VARCHAR2(4000)という定義を持ちます。この属性のデフォルト値はNULLです。named_graphsがNULLの場合、問合せモデルのセット内のすべての名前付きグラフを、GRAPH句によって照合することができます。

network_owner属性は、models属性で指定されたRDFモデルまたは仮想モデルを含むセマンティク・ネットワークを所有するスキーマを指定します。スキーマプライベート・セマンティク・ネットワークを問い合せるには、この属性をnull以外にする必要があります。network_ownerNULL値は、MDSYS所有セマンティク・ネットワークを意味します。

network_name属性は、models属性で指定されたRDFモデルまたは仮想モデルを含むセマンティク・ネットワークの名前を指定します。スキーマプライベート・セマンティク・ネットワークを問い合せるには、この属性をnull以外にする必要があります。network_nameNULL値は、名前のないMDSYS所有セマンティク・ネットワークを意味します。

SEM_MATCH表関数では、入力変数に応じた要素とともにANYDATASET型のオブジェクトが戻されます。次の説明において、varは問合せで使用される変数名を示します。変数varごとに、結果要素にはvarvar$RDFVID、var$_PREFIX、var$_SUFFIX、var$RDFVTYP、var$RDFCLOB、var$RDFLTYPおよびvar$RDFLANGの各属性が含まれます。

このような場合、varはその変数にバインドされた字句の値を保持し、var$RDFVIDは変数にバインドされた値のVALUE_IDを持ちます。var$_PREFIXおよびvar$_SUFFIXは、変数にバインドされた値の接頭辞接尾辞です。var$RDFVTYPは、変数にバインドされた値のタイプ(URILIT [literal]またはBLN [blank node])を示します。var$RDFCLOBは、値がロング・リテラルの場合に変数にバインドされた字句の値を持ちます。var$RDFLTYPは、リテラルがバインドされている場合にそのバインドされたリテラルのタイプを示します。var$RDFLANGは、言語タグ付きのリテラルがバインドされている場合に、そのバインドされたリテラルの言語タグを持ちます。var$RDFCLOBはCLOB型ですが、他のすべての属性はVARCHAR2型です。

リテラル値または空白ノードの場合、接頭辞は値そのものになり、接尾辞はNULLになります。URI値の場合、接頭辞は値の一番右側にある/(スラッシュ)、#(ポンド)または:(コロン)の3つのいずれかの文字から左側の部分となり、接尾辞はそれより右側の値部分となります。たとえば、URI値http://www.example.org/family/grandParentOfの場合、接頭辞はhttp://www.example.org/family/、接尾辞はgrandParentOfとなります。

変数値の列とともに、SPARQL SELECT構文を使用するSEM_MATCH問合せは、追加のNUMBER列であるSEM$ROWNUMを戻します(この列は、SPARQL ORDER BY句を含む問合せの正しい結果順序を保証するために使用できます)。

SPARQL ASK構文を使用するSEM_MATCH問合せは、列ASK、ASK$RDFVID、ASK$_PREFIX、ASK$_SUFFIX、ASK$RDFVTYP、ASK$RDFCLOB、ASK$RDFLTYP、ASK$RDFLANGおよびSEM$ROWNUMを返します。これは、1つの?ask変数を射影するSPARQL SELECT構文の問合せと同じです。

SPARQL CONSTRUCTまたはSPARQL DESCRIBE構文を使用するSEM_MATCH問合せは、問合せ結果バインディングではなくRDFトリプル・データを含む列を返します。これらの問合せは、主語、述語および目的語のコンポーネントについて値を返します。詳細は、「グラフ・パターン: SPARQL CONSTRUCT構文のサポート」を参照してください。

SEM_RELATED演算子を使用してOWLオントロジを問い合せる方法の詳細は、「セマンティク演算子を使用したリレーショナル・データの問合せ」を参照してください。

複数のモデルを問い合せる場合、または1つ以上のモデルおよびそれに対応する伴意を問い合せる場合、パフォーマンスの向上のため、仮想モデルを使用することを考慮してください(「仮想モデル」を参照)。

例1-11 SEM_MATCH表関数

例1-11では、RDFSfamily_rbの2つのルールベースによる推論を使用して、familyモデルからすべての祖父(祖父母の男性の方)とその孫を選択します。(この例は、 「例: 家系の情報」例1-122の抜粋です。)

SELECT x$rdfterm grandfather, y$rdfterm grandchild
  FROM TABLE(SEM_MATCH(
    'PREFIX  rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
     PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
     PREFIX     : <http://www.example.org/family/>
     SELECT ?x ?y
     WHERE {?x :grandParentOf ?y . ?x rdf:type :Male}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null,  null, null,
    ' PLUS_RDFT=VC ',
    null, null,
    'RDFUSER', 'NET1'));

例1-12 SEM_MATCH表関数を使用したHINT0オプション

例1-12例1-11と同じ機能ですが、HINT0オプションが追加されています。

SELECT x$rdfterm grandfather, y$rdfterm grandchild
  FROM TABLE(SEM_MATCH(
    'PREFIX  rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
     PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
     PREFIX     : <http://www.example.org/family/>
     SELECT ?x ?y
     WHERE {?x :grandParentOf ?y . ?x rdf:type :Male}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null,  null, null,
    ' PLUS_RDFT=VC HINT0={LEADING(t0 t1) USE_NL(?x ?y)}',
    null, null,
    'RDFUSER', 'NET1'));

例1-13 SEM_MATCH表関数を使用したDISABLE_SAMEAS_BLOOMオプション

例1-12では、owl:sameAsトリプルが結合されている場合に問合せコンパイラがブルーム・フィルタを使用しないことを指定します。

SELECT select s, o
FROM table(sem_match('{ # HINT0={LEADING(t1 t0) USE_HASH(t0 t1)}
 ?s owl:sameAs ?o. ?o owl:sameAs ?s}', sem_models('M1'), null,null,null,null,
  ' DISABLE_SAMEAS_BLOOM ')) order by 1,2;

例1-14 SEM_MATCH表関数

例1-14では、Pathway/Genome BioPaxオントロジを使用して、ProteinsComplexesの両方に属するすべての化学的複合タイプを取得します。

SELECT t.r 
  FROM TABLE (SEM_MATCH ( 
      'PREFIX : <http://www.biopax.org/release1/biopax-release1.owl>
       SELECT ?r
       WHERE {
        ?r rdfs:subClassOf :Proteins .  
        ?r rdfs:subClassOf :Complexes}', 
      SEM_Models ('BioPax'), 
      SEM_Rulebases ('rdfs'), 
      NULL, NULL, NULL, '', NULL, NULL,
      'RDFUER','NET1')) t;

例1-14のとおり、SEM_MATCH表関数の検索パターンは、変数が疑問符文字(?)で始まるSPARQL構文を使用して指定します。この例の場合、変数?rは、同じ語に一致する必要があるため、ProteinsComplexesの両方のサブクラスである必要があります。

1.6.1 不完全または無効な伴意による問合せの実行

関連する伴意のステータスが無効の場合でも、SEM_MATCH表関数のindex_status属性に文字列値INCOMPLETEまたはINVALIDを指定すると、セマンティク・データを問い合せることができます。(伴意のステータスは、「伴意(ルール索引)」に記載されているとおり、SEM_RULES_INDEX_INFOビューのSTATUS列に格納されます。(SEM_MATCH表関数については、「SEM_MATCH表関数を使用したセマンティク・データの問合せ」を参照してください。)

index_status属性の値は、問合せの動作に次のように影響します。

  • 伴意のステータスが有効の場合、問合せ動作はindex_status属性の値に影響を受けません。

  • index_statusに値を指定しないか、NULL値を指定した場合に、伴意のステータスが無効だと、問合せからエラーが戻されます。

  • index_status属性に文字列INCOMPLETEを指定すると、伴意のステータスが不完全または有効である場合、問合せが実行されます。

  • index_status属性に文字列INVALIDを指定すると、伴意の実際のステータス(無効、不完全または有効)にかかわらず問合せが実行されます。

ただし、伴意のステータスが不完全または無効の場合、次の考慮事項が適用されます。

  • ステータスが不完全の場合、基礎となるモデルに最近挿入されて推論可能となったいくつかのトリプルは、実際には伴意に存在しないことがあり、したがって問合せにより戻される結果は不正確となる可能性があるため、伴意の内容は近似値となる可能性があります。

  • ステータスが無効の場合、基礎となるモデルまたはルールベース(あるいはその両方)が最近変更されて推論不可能となったいくつかのトリプルは、まだ伴意に存在することがあり、したがって問合せにより戻される結果の正確性が影響を受ける可能性があるため、伴意の内容は近似値となる可能性があります。推論不可能となったトリプルが存在する可能性に加え、一部の推論可能な行が実際には伴意に存在しない可能性もあります。

1.6.2 グラフ・パターン: 中カッコの構文とOPTIONAL、FILTER、UNIONおよびGRAPHキーワードのサポート

SEM_MATCH表関数は、一連のトリプル・パターンを中カッコで囲むグラフ・パターンの構文を受け入れます。OPTIONAL、FILTER、UNIONまたはGRAPHキーワードが続く場合以外は、セパレータとしてピリオドが必要です。この構文では、次の操作を任意に組み合せて実行できます。

  • OPTIONAL構成要素を使用して、部分一致の場合にも結果を取得できます。

  • FILTER構成要素を使用して、ソリューションを問合せに制限するグラフ・パターンのフィルタ式を指定できます。

  • UNION構成要素を使用して、複数の代替グラフ・パターンのいずれかを一致させることができます。

  • GRAPH構成要素(「GRAPHキーワード・サポート」を参照)を使用して、グラフ・パターンの一致範囲を名前付きグラフのセットに制限できます。

算術演算子(+、-、*、/)、ブール演算子と論理連結語(||、&&、!)、および比較演算子(<、>、<=、>=、=、!=)に加えて、いくつかの組込み関数をFILTER句で使用できます。表1-13に、FILTER句で使用できる組込み関数を示します。表1-13の「説明」列で、xyおよびzは、適切な型の引数です。

表1-13 FILTER句で使用できる組込み関数

関数 説明

ABS(RDF term)

termの絶対値を戻します。termが数値以外の場合は、nullを戻します。

BNODE(literal)またはBNODE()

問合せのデータセット内のすべての空白ノード、および他の問合せでこの関数によって作成された空白ノードとは別の空白ノードを構築します。引数を指定しない形式では、すべてのコールで異なる空白ノードが構築されます。単純なリテラルを指定する形式の場合、異なる単純なリテラルに対しては異なる空白ノードが構築され、同じ単純なリテラルを使用したコールでは同じ空白ノードが構築されます。

BOUND(variable)

BOUND(x)は、xが結果でバインドされる場合(つまりnull以外の場合)はtrueを戻し、それ以外の場合はfalseを戻します。

CEIL(RDF term)

term以上の最も近い小数部分なしの数値を戻します。termが数値以外の場合は、nullを戻します。

COALESCE(term list)

エラーが発生せずに評価された引数リストの最初の要素を戻します。評価される場合は、バインドされていない変数でエラーが発生します。有効な要素が語句リストにない場合は、nullを戻します。

CONCAT(term list)

語句リスト内の文字列値を連結した結果のxsd:String値を戻します。

CONTAINS(literal, match)

文字列matchliteral内で検出された場合に、trueを戻します。それ以外の場合はfalseを戻します。

DATATYPE(literal)

DATATYPE(x)は、xのデータ型を表すURIを戻します。

DAY(argument)

引数の日部分に対応する整数を戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

ENCODE_FOR_URI(literal)

literal内の予約済文字がエスケープされ、そのパーセントエンコード形式に変換される文字列を戻します。

EXISTS(pattern)

含まれているグループ・グラフ・パターンと現在のアクティブ・グラフ内の現在のバインディングを使用して、パターンが問合せデータセットと一致する場合に、trueを戻します。一致がない場合は、falseを戻します。

FLOOR(RDF term)

termを下回る、最も近い小数部分なしの数を戻します。termが数値以外の場合は、nullを戻します。

HOURS(argument)

argumentの時間部分に対応する整数を戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

IF(condition , expression1, expression2)

条件を評価して、有効なブール値を取得します。trueの場合、最初の式が評価され、その値が戻されます。falseの場合、2つ目の式が使用されます。条件でエラーが発生した場合、エラーはIF文の結果として渡されます。

IRI(RDF term)

引数termの文字列表現を解決するIRIを戻します。問合せで定義されているベースIRIがある場合、IRはそれに対して解決され、結果は絶対IRIになる必要があります。

isBLANK(RDF term)

isBLANK(x)は、xが空白ノードの場合にtrueを戻し、それ以外の場合はfalseを戻します。

isIRI(RDF term)

isIRI(x)は、xがIRIの場合にtrueを戻し、それ以外の場合はfalseを戻します。

isLITERAL(RDF term)

isLiteral(x)は、xがリテラルの場合にtrueを戻し、それ以外の場合はfalseを戻します。

IsNUMERIC(RDF term)

termが数値の場合はtrueを戻し、それ以外の場合はfalseを戻します。

isURI(RDF term)

isURI(x)は、xがURIの場合にtrueを戻し、それ以外の場合はfalseを戻します。

LANG(literal)

LANG(x)は、xの言語タグをシリアライズするプレーン・リテラルを戻します。

LANGMATCHES(literal, literal)

LANGMATCHES(x、y)は、言語タグxが言語レンジyと一致する場合にtrueを戻し、それ以外の場合はfalseを戻します。

LCASE(literal)

リテラル内の各文字を対応する子文字に変換して、文字列を戻します。

MD5(literal)

MD5ハッシュ関数に対応する、literalのチェックサムを戻します。

MINUTES(argument)

argumentの分部分に対応する整数を戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

MONTH(argument)

argumentの月部分に対応する整数を戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

NOT_EXISTS(pattern)

含まれているグループ・グラフ・パターンと現在のアクティブ・グラフ内の現在のバインディングを使用して、パターンが問合せデータセットと一致しない場合に、trueを戻します。それ以外の場合はfalseを戻します。

NOW()

問合せ実行時点の現在の時刻に対応するxsd:dateTime値を戻します。

RAND()

[0,1)のレンジ内の数値を生成します。

REGEX(string, pattern)

REGEX(x,y)は、xが正規表現yに一致する場合にtrueを戻し、それ以外の場合はfalseを戻します。サポートされる正規表現の詳細は、『Oracle Database SQL言語リファレンス』の付録「Oracleの正規表現のサポート」を参照してください。

REGEX(string, pattern, flags)

REGEX (x,y,z)は、xzに指定されたオプションを使用して正規表現yと一致する場合にtrueを戻し、それ以外の場合はfalseを戻します。使用可能なオプション: 's'はドットがすべてに一致するモード('.'は改行文字を含む任意の文字と一致)、'm'は複数行モード('^'は任意の行の先頭と一致し、'$'は任意の行の末尾と一致)、'i'は大/小文字を区別しないモード、'x'は照合前に正規表現から空白文字を削除します。

REPLACE(string, pattern, replacement)

string内の正規表現patternの一致箇所が、それぞれreplacementに置き換えられた文字列を戻します。サポートされる正規表現の詳細は、『Oracle Database SQL言語リファレンス』の付録「Oracleの正規表現のサポート」を参照してください。

REPLACE(string, pattern, replacement, flags)

string内の正規表現patternの一致箇所が、それぞれreplacementに置き換えられた文字列を戻します。使用可能なオプション: 's'はドットがすべてに一致するモード('.'は改行文字を含む任意の文字と一致)、'm'は複数行モード('^'は任意の行の先頭と一致し、'$'は任意の行の末尾と一致)、'i'は大/小文字を区別しないモード、'x'は照合前に正規表現から空白文字を削除します。

サポートされる正規表現の詳細は、『Oracle Database SQL言語リファレンス』の付録「Oracleの正規表現のサポート」を参照してください。

ROUND(RDF term)

termに最も近い小数部分なしの数を戻します。2つの値が存在する場合、正の無限大に近い方の値が戻されます。termが数値以外の場合は、nullを戻します。

sameTerm(RDF term, RDF term)

sameTerm(x, y)は、xおよびyが同じRDF語句の場合にtrueを戻し、それ以外の場合はfalseを戻します。

SECONDS(argument)

argumentの秒部分に対応する整数を戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

SHA1(literal)

SHA1ハッシュ関数に対応する、literalのチェックサムを戻します。

SHA256(literal)

SHA256ハッシュ関数に対応する、literalのチェックサムを戻します。

SHA384(literal)

SHA384ハッシュ関数に対応する、literalのチェックサムを戻します。

SHA512(literal)

SHA512ハッシュ関数に対応する、literalのチェックサムを戻します。

STR(RDF term)

STR(x)は、xの文字列表現のプレーン・リテラル(つまり、二重引用符で囲まれた、MDSYS.RDF_VALUE$のVALUE_NAME列に格納される内容)を戻します。

STRAFTER(literal, literal)

StrAfter (x,y)は、x内でyの最初の一致からxの末尾までの部分文字列に対応する文字列部分を戻します。x内にyの一致がない場合は、空の文字列が戻されます。

STRBEFORE(literal, literal)

StrBefore (x,y)は、xの先頭からyの最初の一致までに対応する文字列部分を戻します。x内にyの一致がない場合は、空の文字列が戻されます。

STRDT(string, datatype)

引数として渡されるstring字句形式とdatatypeで構成されるリテラル語句を構築します。datatypeはURIである必要があり、そうでない場合はNULL値を戻します。

STRENDS(literal, match)

文字列literalが文字列matchで終わる場合にtrueを戻します。それ以外の場合はfalseを戻します。

STRLANG (string, languageTag)

引数として渡されたstring字句形式と言語タグから成る文字列を構築します。

STRLEN(literal)

literalの字句形式の長さを戻します。

STRSTARTS(literal, match)

文字列literalが文字列matchで始まる場合に、trueを戻します。それ以外の場合はfalseを戻します。

STRUUID()

新しいUUIDのスキーム・セクションを含む文字列を戻します。

SUBSTR(term, startPos)

startPosからtermの末尾までの、termの部分と対応する文字列を戻します。先頭文字の索引は1です。

SUBSTR(term, startPos, length)

startPosからlength文字までの、termの部分に対応する文字列を戻します。先頭文字の索引は1です。

term IN (term list)

xtermlistの値のいずれかで検出できた場合、式x IN(term list)はtrueを戻します。検出されない場合は、falseを戻します。長さ0のリストは有効です。termlistの値のいずれかでエラーが発生すると、エラーのためxは検出されません。

term NOT IN (term list)

xをterm listの値のいずれかで検出できた場合、式x NOT IN(term list)はfalseを戻します。検出されない場合は、trueを戻します。長さ0のリストは有効です。term listの値のいずれかでエラーが発生すると、エラーのためxは検出されません。

TIMEZONE(argument)

xsd:dayTimeDuration値としてargumentのタイムゾーン・セクションを戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

TZ(argument)

argumentのタイムゾーン部分に対応する整数を戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

UCASE(literal)

literal内の各文字を対応する大文字に変換して、文字列を戻します。

URI(RDF term)

IRI(RDF term)のシノニム

UUID()

新しいUniversal Unique Identifierを含むURIを戻します。この値およびバージョンは、PL/SQL関数sys_guid ()と対応します。

YEAR(argument)

argumentの年部分に対応する整数を戻します。

SEM_MATCHで使用可能な組込み関数の理解を深めるには、SPARQL問合せ言語指定(http://www.w3.org/TR/sparql11-query/)において定義される組込み関数の説明も参照してください。

さらに、Oracle Databaseの機能を利用したOracle独自の問合せ関数も用意されています。こうした関数は問合せでのパフォーマンス向上に有効です。次の表に、こうしたOracle固有の関数を一覧で示します。なお、組込みの接頭辞orardfは、<http://xmlns.oracle.com/rdf/>に展開されます。

表1-14 Oracle固有の問合せ関数

関数 説明

orardf:like(RDF term, pattern)

指定したtermが、指定したpatternと相似パターン上で合致する場合にtrueを返し、そうでない場合にはfalseを返します。詳細は、「全文検索」を参照してください。

orardf:sameCanonTerm(RDF term, RDF term)

2つのtermが、同じ正規のRDF語句である場合にtrueを返し、そうでない場合にfalseを返します。VALUE_IDに基づく比較ができるため、sameTerm(?x, ?y) or (?x = ?y)よりも効率的です。

orardf:textContains(RDF term, pattern)

指定したtermが、指定したpatternとOracle Text検索パターン上で合致する場合にtrueを返し、そうでない場合にはfalseを返します。詳細は、「全文検索」を参照してください。

orardf:textScore(invocation id)

orardf:textContainsによる照合時のスコアを返します。詳細は、「全文検索」を参照してください。

(組込みの空間関数)

(「空間のサポート」を参照)

次のXMLスキーマをキャストする関数は、FILTER句で使用できます。これらの関数は、RDF語句を入力として取得して必要な型の新しいRDF語句を戻すか、RDF語句を目的の型にキャストできない場合はエラーを発生させます。型キャストの詳細は、XPath問合せの仕様(http://www.w3.org/TR/xpath-functions/#casting-from-primitive-to-primitive)の17.1項を参照してください。これらの関数は、XMLネームスペースxsd : http://www.w3.org/2001/XMLSchema#を使用します。

  • xsd:string (RDF term)

  • xsd:dateTime (RDF term)

  • xsd:boolean (RDF term)

  • xsd:integer (RDF term)

  • xsd:float (RDF term)

  • xsd:double (RDF term)

  • xsd:decimal (RDF term)

中カッコを含む構文を使用してグラフ・パターンを表現した場合、次のようになります。

  • 問合せは常に、変数の一致する値の正規字句形式を戻します。

  • options引数にHINT0={<hint-string>}を使用して指定するヒント(「SEM_MATCH表関数を使用したセマンティク・データの問合せ」を参照)は、ルートBGP内のグラフ・パターン部分に基づいてのみ構築する必要があります。たとえば、例1-16の問合せのヒント指定で使用できる有効な別名は、t0t1?xおよび?yのみです。インライン問合せオプティマイザ・ヒントを使用すると、グラフ・パターンの他の部分に影響を与えることができます(「インライン問合せオプティマイザ・ヒント」を参照)。

  • FILTER構成要素は、ロング・リテラルにバインドされた変数ではサポートされません。

例1-15 中カッコの構文

例1-15は、中カッコとピリオドを含む構文を使用してSEM_MATCH表関数内のグラフ・パターンを表現しています。

SELECT x, y
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, '', null, null,
    'RDFUSER', 'NET1'));

例1-16 中カッコの構文およびOPTIONAL構成要素

例1-16では、各祖父の参加する試合の名前(いずれの試合にも参加しない場合はNULL)も戻されるように、OPTIONAL構成要素を使用して例1-15を変更しています。

SELECT x, y, game
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male . 
      OPTIONAL{?x :plays ?game} 
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null,
    null,
    'HINT0={LEADING(t0 t1) USE_NL(?x ?y)}', 
    null, 
    null,
    'RDFUSER', 'NET1'));

例1-17 中カッコの構文および複数パターンのOPTIONAL構成要素

OPTIONALグラフ・パターンに複数のトリプル・パターンが存在すると、オプションの変数の値は、OPTIONALグラフ・パターンの各トリプル・パターンに一致が検出された場合のみ戻されます。例1-17例1-16を変更したもので、祖父ごとに、祖父と孫の両方が参加する試合の名前、または祖父と孫に共通の試合がない場合はnullが戻されるようになっています。ここでは、グローバル問合せオプティマイザ・ヒントも使用して、トリプル・パターンが各BGP内で順番に評価される必要があること、およびルートBGPをOPTIONAL BGPと結合するためにハッシュ結合を使用する必要があることを指定しています。

SELECT x, y, game
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male . 
      OPTIONAL{?x :plays ?game . ?y :plays ?game} 
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null,
    'ALL_ORDERED ALL_BGP_HASH', 
    null, null,
    'RDFUSER', 'NET1'));

例1-18 中カッコの構文およびネストしたOPTIONAL構成要素

単一の問合せに複数のOPTIONALグラフ・パターンを含むことが可能であり、ネスト化またはパラレル化することもできます。例1-18は、例1-17を変更してOPTIONALグラフ・パターンをネスト化したものです。この例では、祖父ごとに、(1)祖父が参加した試合、または祖父が試合に参加しなかった場合はnullを戻し、(2)祖父が試合に参加した場合は同じ試合に参加した孫の年齢、または孫と共通の試合がなかった場合はnullを戻します。例1-18では、ネストされたOPTIONALグラフ・パターン「?y :plays ?game . ?y :age ?age」が一致しない場合でも、?gameに対して値が戻される点に注意してください。

SELECT x, y, game, age
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male . 
      OPTIONAL{?x :plays ?game 
                          OPTIONAL {?y :plays ?game . ?y :age ?age} } 
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-19 中カッコの構文およびパラレルのOPTIONAL構成要素

例1-19では、パラレルのOPTIONALグラフ・パターンを使用して例1-17を変更しています。この例では、各祖父について、(1)祖父の参加する試合(いずれの試合にも参加しない場合はNULL)、および(2)祖父の電子メール・アドレス(電子メール・アドレスがない場合はNULL)が戻されます。ネストしたOPTIONALグラフ・パターンとは異なり、パラレルのOPTIONALグラフ・パターンはそれぞれ個別に処理されます。つまり、電子メール・アドレスが見つかると、それは試合が見つかったかどうかにかかわらず戻され、試合が見つかると、それは電子メール・アドレスが見つかったかどうかにかかわらず戻されます。

SELECT x, y, game, email
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male . 
      OPTIONAL{?x :plays ?game}
      OPTIONAL{?x :email ?email} 
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-20 中カッコの構文およびFILTER構成要素

例1-20では、NYまたはCAに居住している祖父のみの孫の情報が戻されるように、FILTER構成要素を使用して例1-15を変更しています。

SELECT x, y
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male . ?x :residentOf ?z
       FILTER (?z = "NY"  || ?z = "CA")}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-21 中カッコの構文とREGEXおよびSTR組込み関数を使用したFILTER構成要素

例1-21では、REGEX組込み関数を使用して、Oracle電子メール・アドレスを持つすべての祖父を選択しています。正規表現パターン内のバックスラッシュ(\)文字は、問合せ文字列内でエスケープする必要があります(たとえば\\.はパターン\.となります)。

SELECT x, y, z
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male . ?x :email ?z
       FILTER (REGEX(STR(?z), "@oracle\\.com$"))}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-22 中カッコの構文とUNIONおよびFILTER構成要素

例1-22では、祖父がNYまたはCAに居住しているか、NYまたはCAに不動産を所有している場合にのみ、あるいは両方の条件がtrueの場合(祖父がNYまたはCAに居住し、かつ不動産を所有している場合)に祖父が戻されるように、UNION構成要素を使用して例1-20を変更しています。

SELECT x, y
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male 
       {{?x :residentOf ?z} UNION {?x :ownsPropertyIn ?z}}
       FILTER (?z = "NY"  || ?z = "CA")}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));
1.6.2.1 GRAPHキーワード・サポート

SEM_MATCH問合せは、RDFデータセットに対して実行されます。RDFデータセットは、1つの名前なしグラフ(デフォルト・グラフ)および1つ以上の名前付きグラフを含むグラフのコレクションです(URIで識別されます)。GRAPH句に出現するグラフ・パターンは名前付きグラフのセットに対して照合され、GRAPH句に出現しないグラフ・パターンはデフォルト・グラフに対して照合されます。graphsおよびnamed_graphs SEM_MATCHパラメータは、SEM_MATCH問合せに対してデフォルト・グラフおよび名前付きグラフのセットを構築するために使用されます。可能なデータセットの構成を、表1-15にまとめます。

表1-15 SEM_MATCHのgraphsとnamed_graphsの値、および結果のデータセット構成

パラメータの値 デフォルトのグラフ 名前付きグラフのセット

graphs: NULL

named_graphs: NULL

すべての名前なしトリプルと、すべての名前付きグラフ・トリプルのすべての和集合。(ただし、optionsパラメータにSTRICT_DEFAULT=Tが含まれる場合は、名前なしトリプルのみがデフォルト・グラフに含められます。)

すべての名前付きグラフ

graphs: NULL

named_graphs: {g1,…, gn}

空のセット

{g1,…, gn}

graphs: {g1,…, gm}

named_graphs: NULL

{g1,…, gm}のUNION ALL

空のセット

graphs: {g1,…, gm}

named_graphs: {gn,…, gz}

{g1,…, gm}のUNION ALL

{gn,…, gz}

RDFデータセットとGRAPH構成要素の詳細は、W3C SPARQL仕様、特にhttp://www.w3.org/TR/rdf-sparql-query/#rdfDatasetも参照してください。

例1-23 名前付きグラフの構成要素

例1-23では、GRAPH構成要素を使用して、グラフ・パターン照合の範囲を特定の名前付きグラフに指定しています。この例では、<http://www.example.org/family/Smith>名前付きグラフで、すべての人の名前および電子メール・アドレスを検出します。

SELECT name, email
  FROM TABLE(SEM_MATCH(
    '{GRAPH :Smith {
       ?x :name ?name . ?x :email ?email } }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-24 named_graphsパラメータの使用

URIの他に、GRAPHキーワードの後に変数を使用できます。例1-24では、GRAPHキーワードとともに変数?gを使用し、named_graphsパラメータを使用して、?gの可能な値を、<http://www.example.org/family/Smith>および<http://www.example.org/family/Jones>名前付きグラフに制限しています。SEM_ALIASES引数で指定される別名は、graphsおよびnamed_graphsパラメータで使用できます。

SELECT name, email
  FROM TABLE(SEM_MATCH(
    '{GRAPH ?g {
       ?x :name ?name . ?x :email ?email } }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null,null,null,null,
    SEM_GRAPHS('<http://www.example.org/family/Smith>',
               ':Jones'),
    'RDFUSER', 'NET1'));

例1-25 graphsパラメータの使用

例1-25では、デフォルト・グラフを使用して、<http://www.example.org/family/Smith><http://www.example.org/family/Jones>名前付きグラフの和集合を問い合せています。

FROM TABLE(SEM_MATCH(
    '{?x :name ?name . ?x :email ?email }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null,null,null,
    SEM_GRAPHS('<http://www.example.org/family/Smith>', 
               ':Jones'),
    null,
    'RDFUSER', 'NET1'));

1.6.3 グラフ・パターン: SPARQL ASK構文のサポート

SEM_MATCHでは、問合せパラメータに完全指定のSPARQL ASK問合せを使用できます。

ASK問合せは、指定の問合せパターンに対する解が存在するかどうかをテストするために使用されます。他の形式のSPARQL問合せとは異なり、ASK問合せでは問合せパターンの解に関する情報は返されません。かわりに、解が存在する場合は"true"^^xsd:boolean、解が存在しない場合は"false"^^xsd:booleanが返されます。

すべてのSPARQL ASK問合せは同じ列(ASK、ASK$RDFVID、ASK$_PREFIX、ASK$_SUFFIX、ASK$RDFVTYP、ASK$RDFCLOB、ASK$RDFLTYP、ASK$RDFLANG、SEM$ROWNUM)を返します。これらの列は、1つの?ask変数を射影するSPARQL SELECT構文の問合せと同じであることに注意してください。

SPARQL ASK問合せは、同等のSPARQL SELECT構文の問合せよりもパフォーマンスが高くなります。ASK問合せは、問合せ変数の字句の値を取得する必要がなく、1つの結果が見つかると問合せの実行を停止できるためです。

SPARQL ASK問合せはSPARQL SELECT問合せと同じ構文を使用しますが、最上位のSELECT句をキーワードASKで置き換える必要があります。

例1-26 SPARQL ASK

例1-26に、10メガ・ピクセル超で50ドル未満のカメラが売り出されているかどうかを判別するSPARQL ASK問合せを示します。

SELECT ask
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     ASK
     WHERE
      {?x :price ?p .
       ?x :megapixels ?m .
       FILTER (?p < 50 && ?m > 10)
      }',
    SEM_Models('electronics'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

SPARQL ASK問合せの詳細は、W3C SPARQL仕様、特にhttp://www.w3.org/TR/sparql11-query/#askも参照してください。

1.6.4 グラフ・パターン: SPARQL CONSTRUCT構文のサポート

SEM_MATCHでは、問合せパラメータに完全指定のSPARQL CONSTRUCT問合せを使用できます。

CONSTRUCT問合せは、格納されているRDFデータからRDFグラフを構築するために使用されます。SPARQL SELECT問合せとは対照的に、CONSTRUCT問合せは問合せの解(変数バインディング)のセットではなくRDFトリプルのセットを返します。

すべてのSPARQL CONSTRUCT問合せは、SEM_MATCHから同じ列を返します。これらの列は、RDFトリプルの主語、述語および目的語に対応し、トリプルの構成要素ごとに10個の列があります。この他にSEM$ROWNUM列も返されます。具体的には返される列は次のとおりです。

SUBJ
SUBJ$RDFVID
SUBJ$_PREFIX
SUBJ$_SUFFIX
SUBJ$RDFVTYP
SUBJ$RDFCLOB
SUBJ$RDFLTYP
SUBJ$RDFLANG
SUBJ$RDFTERM
SUBJ$RDFCLBT
PRED
PRED$RDFVID
PRED$_PREFIX
PRED$_SUFFIX
PRED$RDFVTYP
PRED$RDFCLOB
PRED$RDFLTYP
PRED$RDFLANG
PRED$RDFTERM
PRED$RDFCLBT
OBJ
OBJ$RDFVID
OBJ$_PREFIX
OBJ$_SUFFIX
OBJ$RDFVTYP
OBJ$RDFCLOB
OBJ$RDFLTYP
OBJ$RDFLANG
OBJ$RDFTERM
OBJ$RDFCLBT
SEM$ROWNUM

各コンポーネントで、COMP、COMP$RDFVID、COMP$_PREFIX、COMP$_SUFFIX、COMP$RDFVTYP、COMP$RDFCLOB、COMP$RDFLTYPおよびCOMP$RDFLANGは、SPARQL SELECT問合せの同じ列の値に対応します。COMP$RDFTERMはN-Triple構文のVARCHAR2(4000) RDF語句を保持し、COMP$RDFCLBTはN-Triple構文のCLOB RDF語句を保持します。

SPARQL CONSTRUCT問合せはSPARQL SELECT問合せと同じ構文を使用しますが、最上位のSELECT句をCONSTRUCTテンプレートで置き換えます。CONSTRUCTテンプレートは、WHERE句に定義された問合せパターンの結果を使用して結果のRDFグラフの作成方法を決定します。CONSTRUCTテンプレートでは、キーワードCONSTRUCTの後に、中カッコで囲まれた一連のSPARQLトリプル・パターンが続きます。キーワードOPTIONAL、UNION、FILTER、MINUS、BIND、VALUESおよびGRAPHは、CONSTRUCTテンプレートでは使用できません。プロパティ・パス表現もCONSTRUCTテンプレート内で使用できません。ただし、WHERE句内の問合せパターンではこれらのキーワードを使用できます。

SPARQL CONSTRUCT問合せは、次の方法で結果のRDFグラフを構築します。WHERE句から返される結果行ごとに、変数値がCONSTRUCTテンプレートに代入され、1つ以上のRDFトリプルが作成されます。例1-27のWHERE句のグラフ・パターンが次の結果行を返すとします。

E$RDFTERM FNAME$RDFTERM LNAME$RDFTERM

ent:employee1

"Fred"

"Smith"

ent:employee2

"Jane"

"Brown"

ent:employee3

"Bill"

"Jones"

例1-27のSEM_MATCH CONSTRUCT問合せ全体は、6個のRDFトリプルに対応する次の行を返します(問合せパターンの結果行ごとに2個ずつ)。

SUBJ$RDFTERM PRED$RDFTERM OBJ$RDFTERM

ent:employee1

foaf:givenName

"Fred"

ent:employee1

foaf:familyName

"Smith"

ent:employee2

foaf:givenName

"Jane"

ent:employee2

foaf:familyName

"Brown"

ent:employee3

foaf:givenName

"Bill"

ent:employee3

foaf:familyName

"Jones"

SPARQL CONSTRUCTの動作に影響を与えるSEM_MATCH問合せオプションが2つあります。CONSTRUCT_UNIQUE=TおよびCONSTRUCT_STRICT=Tです。CONSTRUCT_UNIQUE=T問合せオプションを使用すると、CONSTRUCT問合せから一意のRDFトリプルのみが返されます。 CONSTRUCT_STRICT=T問合せオプションを使用すると、CONSTRUCT問合せから有効なRDFトリプルのみが返されます。有効なRDFトリプルは、主語の位置にURIまたは空白ノードがあり(1)、述語の位置にURIがあり(2)、目的語の位置にURI、空白ノードまたはRDFリテラルがあります(3)。問合せのパフォーマンスが向上するように、これらの問合せオプションはいずれもデフォルトではオフになっています。

例1-27 SPARQL CONSTRUCT

例1-27に、foafボキャブラリを使用して従業員名のRDFグラフを構築するSPARQL CONSTRUCT問合せを示します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
  FROM TABLE(SEM_MATCH(
    'PREFIX  ent: <http://www.example.org/enterprise/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     CONSTRUCT
      {?e foaf:givenName  ?fname .
       ?e foaf:familyName ?lname 
      }
     WHERE
      {?e ent:fname ?fname .
       ?e ent:lname ?lname 
      }',
    SEM_Models('enterprise'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-28 解の修飾子を含むCONSTRUCT

SPARQLの解の修飾子をCONSTRUCT問合せで使用できます。例1-28に、ORDER BYとLIMITを使用して、最も給与が高い2人の従業員のグラフを構築する方法を示します。LIMIT 2句はCONSTRUCT問合せ全体ではなく問合せパターンに適用されることに注意してください。つまり、問合せパターンは2つの結果行を返しますが、CONSTRUCT問合せ全体は6個のRDFトリプル(?eにバインドされた従業員2人に3個ずつ)を返します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
  FROM TABLE(SEM_MATCH(
    'PREFIX  ent: <http://www.example.org/enterprise/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     CONSTRUCT
      { ?e ent:fname       ?fname .
        ?e ent:lname       ?lname .
        ?e ent:dateOfBirth ?dob }
     WHERE
      { ?e ent:fname  ?fname .
        ?e ent:lname  ?lname .
        ?e ent:salary ?sal
      }
     ORDER BY DESC(?sal)
     LIMIT 2',
    SEM_Models('enterprise'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-29 SPARQL 1.1機能とCONSTRUCT

SPARQL 1.1の機能は、CONSTRUCT問合せパターン内でサポートされます。例1-29に、CONSTRUCT問合せで使用されている副問合せとSELECT式を示します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
  FROM TABLE(SEM_MATCH(
    'PREFIX  ent: <http://www.example.org/enterprise/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     CONSTRUCT
      { ?e foaf:name  ?name }
     WHERE
      { SELECT ?e (CONCAT(?fname," ",?lname) AS ?name)
        WHERE { ?e ent:fname ?fname .
                ?e ent:lname ?lname }
      }',
    SEM_Models('enterprise'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-30 名前付きグラフを含むSPARQL CONSTRUCT

名前付きグラフ・データをSPARQL CONSTRUCT問合せで返すことはできません。W3C SPARQL仕様に従って、RDFクワッドではなくRDFトリプルのみが返されるためです。ただし、FROM、FROM NAMEDおよびGRAPHキーワードは、WHERE句に定義された問合せパターンと一致する場合に使用できます。

例1-30は、名前付きグラフent:g1ent:g2のUNIONのent:nameトリプル、名前付きグラフent:g3ent:dateOfBirthトリプル、および名前付きグラフent:g4ent:ssnトリプルを含むRDFグラフを作成します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
  FROM TABLE(SEM_MATCH(
    'PREFIX  ent: <http://www.example.org/enterprise/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     CONSTRUCT
      { ?e ent:name ?name .
        ?e ent:dateOfBirth ?dob .
        ?e ent:ssn ?ssn
      }
     FROM ent:g1
     FROM ent:g2
     FROM NAMED ent:g3
     FROM NAMED ent:g4
     WHERE
      { ?e foaf:name ?name .
        GRAPH ent:g3 { ?e ent:dateOfBirth ?dob }
        GRAPH ent:g4 { ?e ent:ssn ?ssn } 
      }',
    SEM_Models('enterprise'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-31 SPARQL CONSTRUCTの標準形

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
  FROM TABLE(SEM_MATCH(
    'PREFIX  ent: <http://www.example.org/enterprise/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     CONSTRUCT
      {?e foaf:givenName  ?fname .
       ?e foaf:familyName ?lname 
      }
     WHERE
      {?e ent:fname ?fname .
       ?e ent:lname ?lname 
      }',
    SEM_Models('enterprise'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-32 SPARQL CONSTRUCTの短縮形

CONSTRUCTテンプレートがWHERE句とまったく同じ場合、CONSTRUCTの短縮形を使用できます。このケースではキーワードCONSTRUCTのみが必要です。WHERE句のグラフ・パターンもCONSTRUCTテンプレートとして使用されます。例1-32に、例1-31の短縮形を示します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
  FROM TABLE(SEM_MATCH(
    'PREFIX  ent: <http://www.example.org/enterprise/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     CONSTRUCT
     WHERE
      {?e ent:fname ?fname .
       ?e ent:lname ?lname 
      }',
    SEM_Models('enterprise'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));
1.6.4.1 SPARQL CONSTRUCTの一般的なワークフロー

SPARQL CONSTRUCTの一般的なワークフローでは、CONSTRUCT問合せを実行して、既存のセマンティク・モデルのRDFトリプル・データを抽出または変換し(あるいは両方を行い)、そのデータを既存または新規セマンティク・モデルにロードします。データのロードは、単純なINSERT文を使用するかSEM_APIS.BULK_LOAD_FROM_STAGING_TABLEプロシージャを実行して行います。

例1-33 SPARQL CONSTRUCTのワークフロー

例1-33は、既存のent:fnameおよびent:lnameトリプルからfoaf:nameトリプルを作成し、それらの新しいトリプルを元のモデルにバルク・ロードします。その後、元のモデルにfoaf:name値を問い合せることができます。

-- Use create table as select to build a staging table 
CREATE TABLE STAB(RDF$STC_sub, RDF$STC_pred, RDF$STC_obj) AS
SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
FROM TABLE(SEM_MATCH(
 'PREFIX  ent: <http://www.example.org/enterprise/> 
  PREFIX foaf: <http://xmlns.com/foaf/0.1/>
  CONSTRUCT
   { ?e foaf:name  ?name }
  WHERE
   { SELECT ?e (CONCAT(?fname," ",?lname) AS ?name)
     WHERE { ?e ent:fname ?fname .
             ?e ent:lname ?lname }
   }',
 SEM_Models('enterprise'),
 null, null, null, null, ' ', null, null,
 'RDFUSER', 'NET1')); 
 

 
-- Bulk load data back into the enterprise model
BEGIN
  SEM_APIS.BULK_LOAD_FROM_STAGING_TABLE(
    model_name=>'enterprise',
    table_owner=>'rdfuser',
    table_name=>'stab',
    flags=>' parallel_create_index parallel=4 ',
    network_owner=>'RDFUSER',
    network_name=>'NET1');
END;
/
 
-- Query for foaf:name data
SELECT e$rdfterm, name$rdfterm
FROM TABLE(SEM_MATCH(
 'PREFIX foaf: <http://xmlns.com/foaf/0.1/>
  SELECT ?e ?name
  WHERE { ?e foaf:name ?name }',
 SEM_Models('enterprise'),
 null, null, null, null, ' ', null, null,
 'RDFUSER', 'NET1'));

SPARQL CONSTRUCT問合せの詳細は、W3C SPARQL仕様、特にhttp://www.w3.org/TR/sparql11-query/#constructも参照してください。

1.6.5 グラフ・パターン: SPARQL DESCRIBE構文のサポート

SEM_MATCHでは、問合せパラメータに完全指定のSPARQL DESCRIBE問合せを使用できます。

SPARQL DESCRIBE問合せは、RDFデータセットの調査に役立ちます。データセットで使用される正確なRDFプロパティの情報を把握していなくても、指定された1つのリソースまたは一連のリソースについて簡単に情報を見つけることができます。DESCRIBE問合せはリソースrの説明を返します。この説明は、主語または目的語の位置にrを含む、問合せデータセットの一連のRDFトリプルです。

CONSTRUCT問合せと同じく、DESCRIBE問合せは結果バインディングのかわりにRDFグラフを返します。したがって、各DESCRIBE問合せはCONSTRUCT問合せと同じ列を返します(戻り列のリストは、「グラフ・パターン: SPARQL CONSTRUCT構文のサポート」を参照してください)。

SPARQL DESCRIBE問合せはSPARQL SELECT問合せと同じ構文を使用しますが、最上位のSELECT句をDESCRIBE句で置き換えます。DESCRIBE句の構成として、DESCRIBEキーワードの後に一連のURIまたは変数(あるいは両方)を空白で区切って指定するか、DESCRIBEキーワードの後に* (1つのアスタリスク)を指定します。

SPARQL DESCRIBE問合せに影響を与えるSEM_MATCH問合せオプションが2つあります。CONSTRUCT_UNIQUE=TおよびCONSTRUCT_STRICT=Tです。CONSTRUCT_UNIQUE=Tによって結果から重複したトリプルが消去され、CONSTRUCT_STRICT=Tによって結果から無効なトリプルが消去されます。これらのオプションは両方ともデフォルトではオフになっています。これらのオプションの詳細は、「グラフ・パターン: SPARQL CONSTRUCT構文のサポート」を参照してください。

SPARQL DESCRIBET問合せの詳細は、W3C SPARQL仕様、特にhttp://www.w3.org/TR/sparql11-query/#describeも参照してください。

例1-34 SPARQL DESCRIBEの短縮形

SPARQL DESCRIBEの短縮形は、一定の1つのURIを記述するために用意されています。短縮形ではDESCRIBE句のみが必要です。例1-34に、SPARQL DESCRIBE問合せの短縮形を示します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
FROM TABLE(SEM_MATCH(
 'DESCRIBE <http://www.example.org/enterprise/emp_1>',
 SEM_Models('enterprise'),
 null, null, null, null, ' ', null, null,
 'RDFUSER', 'NET1'));

例1-35 SPARQL DESCRIBEの標準形

SPARQL DESCRIBEの標準形では、DESCRIBE句とSPARQL問合せパターン(解の修飾子を含む場合もある)が指定されます。例1-35に、所属部門がニュー・ハンプシャーにあるすべての従業員を説明するSPARQL DESCRIBE問合せを示します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
FROM TABLE(SEM_MATCH(
 'PREFIX  ent: <http://www.example.org/enterprise/>
  DESCRIBE ?e
  WHERE 
   { ?e ent:department ?dept .
     ?dept ent:locatedIn "New Hampshire" }',
 SEM_Models('enterprise'),
 null, null, null, null, ' ', null, null,
 'RDFUSER', 'NET1'));

例1-36 DESCRIBE *

例1-35に示す標準形のDESCRIBEでは、DESCRIBE句に指定された変数にバインドされるすべてのリソースが説明されます。例1-35では、問合せパターンから返され、?eにバインドされているすべての従業員が説明されます。DESCRIBE *が使用されると、問合せに含まれるすべての変数が説明されます。

例1-36例1-35を変更したもので、従業員(?eにバインド)と部門(?deptにバインド)の両方を説明しています。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
FROM TABLE(SEM_MATCH(
 'PREFIX  ent: <http://www.example.org/enterprise/>
  DESCRIBE *
  WHERE 
   { ?e ent:department ?dept .
     ?dept ent:locatedIn "New Hampshire" }',
 SEM_Models('enterprise'),
 null, null, null, null, ' ', null, null,
 'RDFUSER', 'NET1'));

1.6.6 グラフ・パターン: SPARQL SELECT構文のサポート

中カッコのグラフ・パターンに加えて、SEM_MATCHでは、queryパラメータに完全指定のSPARQL SELECT問合せを使用できます。SPARQL SELECT構文オプションを使用すると、SEM_MATCHは問合せ構成要素のBASE、PREFIX、SELECT、SELECT DISTINCT、FROM、FROM NAMED、WHERE、ORDER BY、LIMITおよびOFFSETをサポートします。各SPARQL SELECT構文の問合せは、SELECT句とグラフ・パターンを含める必要があります。

SEM_MATCHを使用する場合の中カッコとSPARQL SELECT構文の主な違いは、SPARQL SELECT構文を使用する場合、SPARQL SELECT句に出現している変数のみがSEM_MATCHから戻されるところにあります。

SPARQL SELECT構文を使用する場合、SEM$ROWNUMという1つの追加列がSEM_MATCHから戻されます。このNUMBER列を使用して、結果の順序がSPARQL ORDER BY句で指定された順序と一致するようにSEM_MATCH問合せの結果を並べ替えることができます。

SPARQL ORDER BY句を使用すると、SEM_MATCH問合せの結果を並べ替えることができます。この句によって、指定された問合せの結果を並べ替えるために使用する一連のコンパレータを指定します。コンパレータは、変数、RDF語句、算術演算子(+、-、*、/)、ブール演算子と論理連結語(||、&&、!)、比較演算子(<、>、<=、>=、=、!=)およびFILTER式で使用可能な任意の関数で作成される式で構成されます。

SPARQL SELECT問合せを評価する場合は、次の順序で操作を実行します。

  1. グラフ・パターン照合

  2. グループ化(「グループ化と集計」を参照してください。)

  3. 集計(「グループ化と集計」を参照してください。)

  4. HAVING (「グループ化と集計」を参照してください。)

  5. VALUES (「値の割当て」を参照してください。)

  6. SELECT式

  7. ORDER BY

  8. 射影

  9. DISTINCT

  10. OFFSET

  11. LIMIT

SPARQL BASE、PREFIX、SELECT、SELECT DISTINCT、FROM、FROM NAMED、WHERE、ORDER BY、LIMITおよびOFFSET構成要素については、W3C SPARQL仕様、特にhttp://www.w3.org/TR/sparql11-query/を参照してください。

例1-37 SPARQL PREFIX、SELECTおよびWHERE句

例1-37では、次のSPARQL構成要素を使用しています。

  • SPARQL PREFIX句(http://www.example.org/family/およびhttp://xmlns.com/foaf/0.1/名前空間に対して略称を指定する場合)

  • SPARQL SELECT句: 問合せから抽出する変数のセットを指定します。

  • SPARQL WHERE句: 問合せグラフ・パターンを指定します。

SELECT y, name
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     SELECT ?y ?name
     WHERE
     {?x :grandParentOf ?y . 
      ?x foaf:name ?name }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-37では、y、y$RDFVID、y$_PREFIX、y$_SUFFIX、y$RDFVTYP、y$RDFCLOB、y$RDFLTYP、y$RDFLANG、name、name$RDFVID、name$_PREFIX、name$_SUFFIX、name$RDFVTYP、name$RDFCLOB、name$RDFLTYP、name$RDFLANGおよびSEM$ROWNUMの各列を戻します。

例1-38 SPARQL SELECT * (トリプル・パターン内のすべての変数)

SPARQL SELECT句では、(A)一連の変数または式あるいはその両方(「SELECT句の式」を参照)を指定するか、(B) アスタリスク(*)を使用して、指定されたトリプル・パターンで出現するすべての変数を射影します。例1-38では、SPARQL SELECT句を使用して、指定されたトリプル・パターンで出現するすべての変数を選択しています。

SELECT x, y, name
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     SELECT *
     WHERE
     {?x :grandParentOf ?y . 
      ?x foaf:name ?name }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-39 SPARQL SELECT DISTINCT

DISTINCTキーワードをSELECTの後に使用すると重複結果行を除外できます。例1-39では、SELECT DISTINCTを使用して重複しない名前のみを選択しています。

SELECT name
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     SELECT DISTINCT ?name
     WHERE
     {?x :grandParentOf ?y . 
      ?x foaf:name ?name }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-40 FROMおよびFROM NAMEDを使用したRDFデータセットの指定

SPARQL FROMおよびFROM NAMEDは、問合せに対してRDFデータセット指定する場合に使用します。FROM句はデフォルト・グラフを構成するグラフのセットを指定する場合に使用し、FROM NAMED句は名前付きグラフ・セットを構成するグラフ・セットを指定する場合に使用します。例1-40では、FROMおよびFROM NAMEDを使用して、<http://www.friends.com/friends>および<http://www.contacts.com/contacts>グラフの和集合から電子メール・アドレスと友人を選択し、<http://www.example.org/family/Smith>および<http://www.example.org/family/Jones>グラフから祖父母情報を選択しています。

SELECT x, y, z, email
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     PREFIX friends: <http://www.friends.com/>
     PREFIX contacts: <http://www.contacts.com/>
     SELECT *
     FROM friends:friends
     FROM contacts:contacts
     FROM NAMED :Smith
     FROM NAMED :Jones
     WHERE
     {?x foaf:frendOf ?y .
      ?x :email ?email .
      GRAPH ?g {
        ?x :grandParentOf ?z }
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-41 SPARQL ORDER BY

SPARQL ORDER BY句の場合:

  • 単一の変数の順序付け条件には前後のカッコは不要ですが、より複雑な順序付け条件にはカッコが必要です。

  • オプションのASC()またはDESC()順序修飾子を使用して、それぞれ昇順または降順となる目的の順序を指定できます。デフォルトの順序は昇順です。

  • SEM_MATCHでSPARQL ORDER BYを使用する場合、取り囲んでいるSQLブロック全体を通じて目的の順序を維持するためには、格納側のSQL問合せをSEM$ROWNUMで並べ替える必要があります。

例1-41では、SPARQL ORDER BY句ですべてのカメラを選択し、タイプの降順かつ総額(price * (1 - discount) * (1 + tax))の昇順になるように順序を指定しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT * 
     WHERE
      {?x :price ?p .
       ?x :discount ?d .
       ?x :tax ?t .
       ?x :cameraType ?cType .
      }
     ORDER BY DESC(?cType) ASC(?p * (1-?d) * (1+?t))',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'))
ORDER BY SEM$ROWNUM;

例1-42 SPARQL LIMIT

SPARQL LIMITおよびSPARQL OFFSETは、問合せの解の異なるサブセットを選択するために使用できます。例1-42ではSPARQL LIMITを使用して最も安価なカメラを5つ選択し、例1-43ではSPARQL LIMITおよびOFFSETを使用して5番目から10番目に安価なカメラを選択しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
      }
     ORDER BY ASC(?p)
     LIMIT 5',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'))
ORDER BY SEM$ROWNUM;

例1-43 SPARQL OFFSET

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
      }
     ORDER BY ASC(?p)
     LIMIT 5
     OFFSET 5',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'))
ORDER BY SEM$ROWNUM;

例1-44 完全なURIを使用した問合せ

SPARQL BASEキーワードは、グローバル接頭辞を設定するために使用します。すべての相対IRIは、「Uniform Resource Identifier (URI): Generic Syntax」(RFC3986)(http://www.ietf.org/rfc/rfc3986.txt)の5.2項で説明されている基本的なアルゴリズムを使用して、ベースIRIで解決されます。例1-44は完全なURIを使用する簡単な問合せで、例1-45はベースIRIを使用する同等の問合せです。

SELECT *
  FROM TABLE(SEM_MATCH(
    'SELECT ?employee ?position
     WHERE
      {?x <http://www.example.org/employee> ?p .
       ?p <http://www.example.org/employee/name> ?employee .
       ?p <http://www.example.org/employee/position> ?pos .
       ?pos <http://www.example.org/positions/name> ?position
      }',
    SEM_Models('enterprise'),
    null, 
     null, null, null, ' ', null, null,
   'RDFUSER', 'NET1'))
ORDER BY 1,2;

例1-45 ベースIRIを使用した問合せ

SELECT *
  FROM TABLE(SEM_MATCH(
    'BASE <http://www.example.org/>
     SELECT ?employee ?position
     WHERE
      {?x <employee> ?p .
       ?p <employee/name> ?employee .
       ?p <employee/position> ?pos .
       ?pos <positions/name> ?position
      }',
    SEM_Models('enterprise'),
    null, 
    null, null, null, ' ', null, null,
   'RDFUSER', 'NET1'))
ORDER BY 1,2;

1.6.7 グラフ・パターン: SPARQL 1.1の構成要素のサポート

SEM_MATCHでは、次のSPARQL 1.1の構成要素がサポートされています。

1.6.7.1 SELECT句の式

SELECT句では式を使用して、問合せから式の値を射影することができます。SELECT式は、変数、RDF語句、算術演算子(+、-、*、/)、ブール演算子と論理連結語(||、&&、!)、比較演算子(<、>、<=、>=、=、!=)およびFILTER式で使用可能な任意の関数で構成されます。式は、ASキーワードを使用して別名として単一の変数を指定する必要があり、<expression> AS <alias>フラグメント全体をカッコで囲む必要があります。この別名変数は、問合せで事前に定義することはできません。SELECT式は、前のSELECT式(つまり、SELECT句の前の方で指定された式)の結果を参照する場合があります。

例1-46 SPARQL SELECT式

例1-46では、SELECT式を使用してカメラごとの合計を射影しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ((?p * (1-?d) * (1+?t)) AS ?totalPrice) 
     WHERE
      {?x :price ?p .
       ?x :discount ?d .
       ?x :tax ?t .
       ?x :cameraType ?cType .
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-47 SPARQL SELECT式(2)

例1-47では、2つのSELECT式を使用して、売上税がある場合とない場合の割引価格を射影しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ((?p * (1-?d)) AS ?preTaxPrice) ((?preTaxPrice * (1+?t)) AS ?finalPrice)
     WHERE
      {?x :price ?p .
       ?x :discount ?d .
       ?x :tax ?t .
       ?x :cameraType ?cType .
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));
1.6.7.2 副問合せ

副問合せは、SPARQL SELECT構文で可能です。つまり、完全指定のSPARQL SELECT問合せが、他のSPARQL SELECT問合せ内に埋め込まれる場合があります。副問合せには、問合せのサブコンポーネントからの結果数を制限する場合など、多くの用途があります。

例1-48 SPARQL SELECT副問合せ

例1-48では、最も安価なカメラを製造するメーカーを検索し、このメーカーが製造した他のすべてのカメラを検索するために副問合せを使用しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?c1
     WHERE {?c1 rdf:type :Camera .
            ?c1 :manufacturer ?m .
            {
             SELECT ?m
             WHERE {?c2 rdf:Type :Camera .
                    ?c2 :price ?p .
                    ?c2 :manufacturer ?m .
             }
             ORDER BY ASC(?p)
             LIMIT 1
            }
     }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

副問合せが最初に論理的に評価され、その結果が外部問合せに射影されます。外部問合せから参照できるのは、副問合せのSELECT句で射影された変数のみです。

1.6.7.3 グループ化と集計

グループ化を実行するにはGROUP BYキーワードを使用します。構文上、GROUP BYキーワードはWHERE句の後、および解の修飾子(ORDER BYまたはLIMITなど)の前に使用する必要があります。

集計は、グループ内の結果全体の値を計算するために使用されます。集計は値のコレクションを操作して、結果として単一の値を生成します。SEM_MATCHは、組込みの集計としてCOUNT、SUM、MIN、MAX、AVG、GROUP_CONCATおよびSAMPLEをサポートしています。これらの集計を、表1-16で説明します。

表1-16 組込みの集計

集計 説明

AVG(expression)

グループ内の値に対するexpressionの平均値を返します。

COUNT(* | expression)

expressionがグループ内にバインドされた非エラー値を持つ回数がカウントされ、アスタリスク(*)ではグループ内の結果数がカウントされます。

GROUP_CONCAT(expression [; SEPARATOR = "STRING"])

グループ内の値に関して、expressionの文字列連結を実行します。オプションのセパレータ文字列を指定すると、各値の間にセパレータ文字が配置されます。

MAX(expression)

SPARQL ORDER BYによって定義される順序付けに基づいて、グループ内のexpressionの最大値を戻します。

MIN(expression)

SPARQL ORDER BYによって定義される順序付けに基づいて、グループ内のexpressionの最少値を戻します。

SAMPLE(expression)

グループから単一の任意の値と評価されるexpressionを戻します。

SUM(expression)

グループ内の値に関してexpressionの数値合計を計算します。

グループ化と集計の使用時には、変数参照に特定の制限が適用されます。グループ化変数(GROUP BY句の単一の変数)およびGROUP BY値割当てからの別名変数のみを、SELECT句またはHAVING句内の非集計式で使用できます。

例1-49 簡単なグループ化の問合せ

例1-49に、GROUP BYキーワードを使用してすべての種類のカメラを検索する問合せを示します。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?cType
     WHERE
      {?x rdf:type :Camera .
       ?x :cameraType ?cType .
      }
     GROUP BY ?cType',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
     null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

グループ化問合せは、グループ化式(例1-49?cType)に基づいて問合せ結果をグループのコレクションに分割して、グループ内の各結果がグループ化式に関しては同じ値を持つようにします。グループ操作の最終結果には、各グループに1つの行が含まれます。

例1-50 複雑なグループ化式

グループ化式では、変数、式、または「<expression> as <alias>」の形式を持つ値割当てを1つ以上、ひと続きで指定します。例1-50は、グループ化式で各タイプのコンポーネントを1つずつ使用しているグループ化問合せを示しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?cType ?totalPrice
     WHERE
      {?x rdf:type :Camera .
       ?x :cameraType ?cType .
       ?x :manufacturer ?m .
       ?x :price ?p .
       ?x :tax ?t .
      }
     GROUP BY ?cType (STR(?m)) ((?p*(1+?t)) AS ?totalPrice)',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-51 集計

例1-51では、集計を使用して、各種類のカメラの最高、最低、平均価格を選択しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?cType 
            (MAX(?p) AS ?maxPrice) 
            (MIN(?p) AS ?minPrice) 
            (AVG(?p) AS ?avgPrice)
     WHERE
      {?x rdf:type :Camera .
       ?x :cameraType ?cType .
       ?x :manufacturer ?m .
       ?x :price ?p .
      }
     GROUP BY ?cType',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-52 グループ化なしの集計

集計をグループ化式なしで使用すると、結果セット全体が単一のグループとして処理されます。例1-52では、データセット全体のカメラの合計数を計算しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT (COUNT(?x) as ?cameraCnt)
     WHERE
      { ?x rdf:type :Camera 
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-53 DISTINCTを使用した集計

DISTINCTキーワードは、必要に応じて、集計ごとに修飾子として使用できます。DISTINCTを使用すると、集計を計算する前に各グループから重複値が除外されます。構文上、DISTINCTは集計の最初の引数として使用される必要があります。例1-53では、重複なしのカメラ・メーカー数を検索するためにDISTINCTを使用しています。この場合、STR(?m)の重複値は、カウント前に除外されます。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT (COUNT(DISTINCT STR(?m)) as ?mCnt)
     WHERE
      { ?x rdf:type :Camera .
        ?x :manufacturer ?m
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
     null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-54 HAVING句

制約に基づいてグループをフィルタ処理するには、HAVINGキーワードを使用できます。HAVING式は、変数、RDF語句、算術演算子(+、-、*、/)、ブール演算子と論理連結語(||、&&、!)、比較演算子(<、>、<=、>=、=、!=)、集計、およびFILTER式で使用可能な任意の関数で構成できます。構文上、HAVINGキーワードはGROUP BY句の後、および他の解の修飾子(ORDER BYまたはLIMITなど)の前に使用します。

例1-54では、HAVING式を使用して、200ドル未満のカメラを販売するすべてのメーカーを検索しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?m
     WHERE
      { ?x rdf:type :Camera .
        ?x :manufacturer ?m .
        ?x :price ?p
      }
     GROUP BY ?m
     HAVING (MIN(?p) < 200)
     ORDER BY ASC(?m)',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));
1.6.7.4 否定

SEM_MATCHでは、SPARQL問合せパターンでNOT EXISTSおよびMINUSの2つの形式の否定がサポートされています。NOT EXISTSはグラフ・パターンが一致したかどうかに基づいて結果をフィルタ処理するために使用可能で、MINUSは別のグラフ・パターンとの関係に基づいて解を除外するために使用できます。

例1-55 NOT EXISTSによる否定

例1-55では、NOT EXISTS FILTERを使用して、ユーザー・レビューのないカメラを選択しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
       FILTER( NOT EXISTS({?x :userReview ?r}) )
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-56 EXISTS

逆に、EXISTS演算子は、パターンの一致を確認する場合に使用できます。例1-56では、EXISTS FILTERを使用して、ユーザー・レビューを持つカメラのみを選択しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
       FILTER( EXISTS({?x :userReview ?r}) )
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null, null, ' ', null, null,
    RDFUSER', 'NET1'));

例1-57 MINUSによる否定

例1-57では、MINUSを使用して、例1-55と同じ結果を得ています。MINUSパターンの解と互換性がない解のみが、結果に含まれます。つまり、解がすべての共有変数にMINUSパターンの解と同じ値を持つ場合、それは結果から除外されます。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
       MINUS {?x :userReview ?r}
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-58 NOT EXISTSによる否定(2)

NOT EXISTSとMINUSは2つの異なるスタイルの否定を表し、特定の状況では異なる結果を持ちます。例としては、否定パターンと残りの問合せの間で変数が共有されない場合が挙げられます。たとえば、例1-58のNOT EXISTS問合せでは{?subj ?prop ?obj}がどのトリプルにも一致するためすべての解が除外されますが、例1-59のMINUS問合せでは、共有変数がないため除外される解はありません。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
       FILTER( NOT EXISTS({?subj ?prop ?obj}) )
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-59 MINUSによる否定(2)

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
       MINUS {?subj ?prop ?obj}
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));
1.6.7.5 値の割当て

SEM_MATCHには、値をSPARQL問合せの変数に割り当てる様々な方法が提供されています。

式の値を新しい変数に割り当てる方法には、(1)SELECT句の式、(2)GROUP BY句の式、および(3)BINDキーワードの3つがあります。どの場合も、新しい変数を問合せで事前に定義しておく必要はありません。割当て後は、この新しい変数を問合せで使用して、結果に戻すことが可能です。「SELECT句の式」で説明したように、値割当ての構文は(<expression> AS <alias>)となり、aliasは新しい変数を示し、たとえば((?price * (1+?tax)) AS ?totalPrice)とします。

例1-60 ネストしたSELECT式

例1-60では、ネストしたSELECT式を使用して、カメラの合計価格を計算し、その値を変数(?totalPrice)に割り当てています。その後、この変数を外部問合せのFILTERで使用して、200ドル未満のカメラを検索します。

SELECT *
 FROM TABLE(SEM_MATCH(
   'PREFIX : <http://www.example.org/electronics/> 
    SELECT ?x ?cType ?totalPrice
    WHERE
     {?x :cameraType ?cType .
       { SELECT ?x ( ((?price*(1+?tax)) AS ?totalPrice )
         WHERE { ?x :price ?price .
                 ?x :tax ?tax }
       }
      FILTER (?totalPrice < 200)
     }',
   SEM_Models('electronics'),
   SEM_Rulebases('RDFS'),
   null, null, null, ' ', null, null,
   'RDFUSER', 'NET1'));

例1-61 BIND

BINDキーワードは、基本グラフ・パターン内で値を割り当てるために使用可能で、構文上は同等のネストしたSELECT式より簡潔です。例1-61では、BINDキーワードを使用して、例1-60と論理的に同等な問合せを表しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?totalPrice
     WHERE
      {?x :cameraType ?cType .
       ?x :price ?price .
       ?x :tax ?tax .
       BIND ( ((?price*(1+?tax)) AS ?totalPrice )
       FILTER (?totalPrice < 200)
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
   'RDFUSER', 'NET1'));

例1-62 GROUP BY式

GROUP BY句の値割当ては、その後SELECT句、HAVING句および外部問合せ(ネストしたグループ化問合せの場合)で使用することができます。例1-62では、GROUP BY式を使用して、1000ドル未満の各価格のカメラの最大メガピクセル数を検索しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?totalPrice (MAX(?mp) as ?maxMP)
     WHERE
      {?x rdf:type :Camera .
       ?x :price ?price .
       ?x :tax ?tax .
       GROUP BY ( ((?price*(1+?tax)) AS ?totalPrice )
       HAVING (?totalPrice < 1000)
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null));

例1-63 VALUES

新しい変数に式の値を割り当てる方法には、前述の3つの方法の他にVALUESキーワードを使用する方法があり、順序付けられていない解の順序を取得して、結合操作によって問合せ結果と組み合せることができます。VALUESブロックは、問合せパターン内、またはSPARQL SELECT問合せブロックの末尾の解の修飾子の後に使用できます。VALUES構成要素は、副問合せで使用できます。

例1-63では、VALUESキーワードを使用して、問合せ結果を:Company1製造のDSLRカメラ、または:Company2製造の任意の種類のカメラに制限しています。キーワードUNDEFは、解の順序内でバインドされていない変数を表すために使用されます。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?m
     WHERE 
      { ?x rdf:type :Camera .
        ?x :cameraType ?cType .
        ?x :manufacturer ?m
      }
     VALUES (?cType ?m)
     { ("DSLR" :Company1)
       (UNDEF  :Company2) 
     }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-64 簡略化されたVALUES構文

変数が1つの一般的な例では、簡略化された構文を使用できます。特に、変数および各解の前後のカッコは省略できます。例1-64は、簡略化された構文を使用して、問合せ結果を:Company1または:Company2によって製造されたカメラに制限しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?m
     WHERE 
      { ?x rdf:type :Camera .
        ?x :cameraType ?cType .
        ?x :manufacturer ?m
      }
     VALUES ?m
     { :Company1
       :Company2 
     }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-65 インラインVALUESブロック

例1-65でも、問合せ結果を:Company1または:Company2製造のカメラに制限していますが、問合せパターン内でVALUESブロックを指定しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?m
     WHERE 
      { VALUES ?m { :Company1 :Company2 }
        ?x rdf:type :Camera .
        ?x :cameraType ?cType .
        ?x :manufacturer ?m
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));
1.6.7.6 プロパティ・パス

SPARQLプロパティ・パスは、RDFグラフ内の2つのRDFリソース(ノード)の間の可能なパスを示しています。プロパティ・パスはトリプル・パターンの述語位置に出現するもので、トリプル・パターンの主語からトリプル・パターンの目的語までのパスを形成するプロパティ(エッジ)に制約を適用するために、正規表現のような構文を使用します。プロパティ・パスによって、SPARQL問合せはRDFグラフの任意の長さのパスを照合し、他のグラフ・パターンを表現する簡潔な方法を提供できます。

表1-17に、SPARQLプロパティ・パスの構築に使用可能な構文構成要素を示します。iriはIRIまたは接頭辞の付いた名前で、eltはプロパティ・パス要素で、それ自体が他のプロパティ・パス要素で構成される場合があります。

表1-17 プロパティ・パスの構文の構成要素

構文の構成要素 一致

iri

IRIまたは接頭辞の付いた名前。長さが1のパス。

^elt

逆のパス(目的語から主語へ)。

!iriまたは!(iri1 | … | irin)

否定プロパティ・セット。 iriiのいずれかではないIRI。

!^iriまたは!(iri1 | … | irij | ^irij+1 | … | ^irin)

逆のプロパティを持つ否定プロパティ・セット。iriiまたはirij+1...irinのいずれでもない逆パスのIRI。!^iri!(^iri)の短縮形。プロパティと逆のプロパティの順番は、どちらが先でも問題ありません。順不同で実行されます。

(elt)

グループ・パスelt(カッコは優先順位を制御します)。

elt1 / elt2

elt1elt2の順の順序パス。

elt1 | elt2

elt1またはelt2の代替パス(すべての可能性が試行されます)。

elt*

0個以上のeltのパス。

elt+

1個以上のeltのパス。

elt?

0個または1個のeltのパス。

構文構成要素の優先順位を、高いものから順に示します。

  • IRI、接頭辞の付いた名前

  • 否定プロパティ・セット

  • グループ

  • 単項演算子 *、?、+

  • 単項^逆リンク

  • バイナリ演算子 /

  • バイナリ演算子 |

グループ内の優先順位は左から右に評価されます。

プロパティ演算子+および*の特別な考慮事項

通常、+ (プラス記号)と* (アスタリスク)演算子を使用した、完全に無制限のグラフ・トラバースはコストが非常に高くなります。この理由から、デフォルトでは深度制限のある+演算子と*演算子が使用されます。デフォルトの深度制限は10です。また、深度制限の実装は並列で実行できます。ALL_MAX_PP_DEPTH(n) SEM_MATCH問合せオプションまたはMAX_PP_DEPTH(n)インラインHINT0問合せオプティマイザ・ヒントを使用して、深度制限設定を変更できます。完全に無制限のトラバースを実現するには、深度制限を1未満に設定して、CONNECT BYベースの実装に戻ります。

プロパティ・パスの問合せヒント

プロパティ・パス問合せのパフォーマンスに影響するその他の問合せヒントも使用できます。ALLOW_PP_DUP=T問合せオプションを*問合せや+問合せと使用すると、結果の重複を認めることができます。結果の重複が認められると、問合せから最初の行が早く戻されます。また、ALL_USE_PP_HASHおよびALL_USE_PP_NL問合せオプションは、プロパティ・パス表現を評価するときに使用される結合タイプに影響します。同様のUSE_PP_HASHおよびUSE_PP_NLインラインHINT0問合せオプティマイザ・ヒントも使用できます。

例1-66 SPARQLプロパティ・パス(rdfs:subClassOf関係を使用)

例1-66では、プロパティ・パスを使用して、rdfs:subClassOf関係の推移性に基づいてすべての男性を検索しています。プロパティ・パスでは、任意の数の連続的なrdfs:subClassOf関係の一致が可能です。

SELECT x, name
  FROM TABLE(SEM_MATCH(
    '{ ?x foaf:name ?name .
       ?x rdf:type ?t .
       ?t rdfs:subClassOf* :Male }',
    SEM_Models('family'),
    null, 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/') 
                SEM_ALIAS('foaf',' http://xmlns.com/foaf/0.1/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-67 SPARQLプロパティ・パス(foaf:friendOfまたはfoaf:knows関係を使用)

例1-67では、プロパティ・パスを使用して、Scottの親しい友人(foaf:friendOfまたはfoaf:knows関係を使用して2ホップ以内に到達可能な人々)をすべて検索しています。

SELECT name
  FROM TABLE(SEM_MATCH(
    '{ { :Scott (foaf:friendOf | foaf:knows) ?f }
       UNION
       { :Scott (foaf:friendOf | foaf:knows)/(foaf:friendOf | foaf:knows) ?f }
       ?f foaf:name ?name .
       FILTER (!sameTerm(?f, :Scott)) }',
    SEM_Models('family'),
    null, 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/'),
                SEM_ALIAS('foaf',' http://xmlns.com/foaf/0.1/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-68 プロパティ・パスの最大深度値の指定

例1-68では、ALL_MAX_PP_DEPTH(n)問合せオプション値を使用してすべてのプロパティ・パス表現に最大深度12を指定します。

SELECT x, name
  FROM TABLE(SEM_MATCH(
    '{ ?x foaf:name ?name .
       ?x rdf:type ?t .
       ?t rdfs:subClassOf* :Male }',
    SEM_Models('family'),
    null, 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/') 
                SEM_ALIAS('foaf',' http://xmlns.com/foaf/0.1/')),
    null,
    null,
    ' ALL_MAX_PP_DEPTH(12) ', 
    null, null,
    'RDFUSER', 'NET1'));

例1-69 プロパティ・パス結合ヒントの指定

例1-69に、プロパティ・パス表現の評価にネステッド・ループ結合をリクエストするインラインHINT0問合せオプティマイザ・ヒントを示します。

SELECT x, name
  FROM TABLE(SEM_MATCH(
    '{ # HINT0={ USE_PP_NL }
       ?x foaf:name ?name .
       ?x rdf:type ?t .
       ?t rdfs:subClassOf* :Male }',
    SEM_Models('family'),
    null, 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/') 
                SEM_ALIAS('foaf',' http://xmlns.com/foaf/0.1/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

1.6.8 グラフ・パターン: SPARQL 1.1のフェデレーテッド問合せのサポート

SEM_MATCHは、SPARQL 1.1のフェデレーテッド問合せをサポートしています(http://www.w3.org/TR/sparql11-federated-query/#SPROTを参照)。SERVICE構成要素を使用して、指定したSPARQLエンドポイントURLから結果を取得できます。この機能により、ローカルのRDFデータ(ネイティブRDFデータまたはリレーショナル・データのRDFビュー)を、W3C標準準拠のSPARQLエンドポイントによって提供される他のRDFデータ(おそらくリモート)と組み合せることができます。

例1-70 すべてのトリプルを取得するSPARQL SERVICE句

例1-70は、SERVICE句を使用して、http://www.example1.org/sparqlにあるSPARQLエンドポイントからすべてのトリプルを取得する問合せです。

SELECT s, p, o
  FROM TABLE(SEM_MATCH(
    'SELECT ?s ?p ?o
     WHERE {
       SERVICE <http://www.example1.org/sparql>{ ?s ?p ?o }
     }',
    SEM_Models('electronics'),
    null, null, null, null, ' ', 
    null, null,
    'RDFUSER', 'NET1'));

例1-71 リモートとローカルのRDFデータを結合するSPARQL SERVICE句

例1-71は、リモートRDFデータとローカルRDFデータを結合します。この例は、ローカル・モデルelectronicsのカメラのタイプ?cTypeを、http://www.example1.org/sparqlのSPARQLエンドポイントのカメラの名前?nameに結合します。

SELECT cType, name
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?cType ?name
     WHERE {
       ?s :cameraType ?cType
       SERVICE <http://www.example1.org/sparql>{ ?s :name ?name }
      }',
    SEM_Models('electronics'),
    null, null, null, null, ' ', 
    null, null,
    'RDFUSER', 'NET1'));
1.6.8.1 フェデレーテッドSPARQL問合せの実行に必要な権限

SEM_MATCH問合せでSERVICE構成要素を使用するには、特定のデータベース権限が必要です。DBA権限を持つユーザーによって、SPARQL_SERVICE MDSYS関数のEXECUTE権限が付与される必要があります。次の例では、このアクセス権がRDFUSERという名前のユーザーに付与されます。

grant execute on mdsys.sparql_service to rdfuser;

また、アクセス制御リスト(ACL)を使用して、フェデレーテッド問合せを試行するユーザーにCONNECT権限を付与する必要があります。例1-72は、新しいACLを作成して、ユーザーRDFUSERにCONNECT権限を付与し、ドメイン*をACLに割り当てます。ACLの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。

例1-72 アクセス制御リストとホスト割当て

dbms_network_acl_admin.create_acl (
  acl       => 'rdfuser.xml',
  description => 'Allow rdfuser to query SPARQL endpoints',
  principal => 'RDFUSER',
  is_grant  => true,
  privilege => 'connect'
);
 
dbms_network_acl_admin.assign_acl (
  acl  => 'rdfuser.xml',
  host => '*'
);      

必要な権限が付与されると、SEM_MATCHからフェデレーテッド問合せを実行する準備が整います。

1.6.8.2 SPARQL SERVICEの結合プッシュ・ダウン

SPARQL SERVICEの結合プッシュ・ダウン(SERVICE_JPDWN=T)機能を使用すると、特定のSPARQL SERVICE問合せのパフォーマンスを改善できます。デフォルトでは、SERVICE句の問合せパターンがリモートSPARQLエンドポイントで最初に実行されます。このリモート実行のすべての結果が、問合せのローカルの部分に結合されます。この方法では、問合せのローカル部分の選択性が非常に高く、問合せのリモート部分の選択性が非常に低いと、パフォーマンスが低下することがあります。

SPARQL SERVICEの結合プッシュ・ダウン機能は、SERVICE句を複数含む問合せでは使用できません。

例1-73 SPARQL SERVICEの結合プッシュ・ダウン

例1-73に、SPARQL SERVICEの結合プッシュ・ダウン機能を示します。

SELECT s, prop, obj
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?s ?prop ?obj
     WHERE {
       ?s rdf:type   :Camera .
       ?s :modelName "Camera 12345"
       SERVICE <http://www.example1.org/sparql> { ?s ?prop ?obj }
      }',
    SEM_Models('electronics'),
    null, null, null, null, ' SERVICE_JPDWN=T ', 
    null, null,
    'RDFUSER', 'NET1'));

例1-73では、問合せのローカル部分ではごく少数の行が返されますが、問合せのリモート部分は完全に無制限であるためリモート・データセット全体が返されます。SERVICE_JPDWN=Tオプションが指定されると、SEM_MATCHはネステッド・ループ方式の評価を実行します。まず、問合せのローカル部分を実行してから、ローカル部分によって返された行ごとに、変更したリモート問合せを1回ずつ実行します。結合変数?sにかわって効率よく実行するFILTER句を使用してリモート問合せを変更します。たとえば、<urn:camera1><urn:camera2>?sのバインディングとして例1-73のローカル部分から返されると、2つの問合せ、{ ?s ?prop ?obj FILTER (?s = <urn:camera1>) }{ s ?prop ?obj FILTER (?s = <urn:camera2>) }がリモート・エンドポイントに送られます。

1.6.8.3 SPARQL SERVICE SILENT

SILENTキーワードがフェデレーテッド問合せで使用されるとき、指定されたリモートSPARQLエンドポイントにアクセスする際のエラーが無視されます。SERVICE SILENTリクエストが失敗すると、バインディングなしの1つの解が返されます。

例1-74は、OPTIONAL句内でSILENTキーワードと一緒にSERVICEを使用しています。このため、http://www.example1.org/sparqlにアクセスする際に接続エラーが発生しても、そのようなエラーは無視され、トリプル?s :cameratype ?kから取得されたすべての行が?nのnull値と結合されます。

例1-74 SILENTキーワードを含むSPARQL SERVICE

SELECT s, n
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?s ?n
     WHERE {
       ?s :cameraType ?k
       OPTIONAL { SERVICE SILENT <http://www.example1.org/sparql>{ ?k :name ?n } }
      }',
    SEM_Models('electronics'),
    null, null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));
1.6.8.4 SPARQL SERVICEでのプロキシ・サーバーの使用

次の方法を使用して、SPARQL SERVICEリクエストをHTTPプロキシで送信できます。

  • 現在のセッションでリクエストに使用する必要があるHTTPプロキシを指定します。これは、UTL_HTTPパッケージのSET_PROXY関数を使用して行うことができます。例1-75は、HTTPリクエストで使用するプロキシproxy.example.comを設定し、ドメインexample2.comのホストに対するリクエストを除外します。(SET_PROXYプロシージャの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。)

  • SPARQL SERVICEリクエストのプロキシ・アドレスを設定できるようにするSERVICE_PROXY SEM_MATCHオプションを使用します。ただし、このケースでは例外を指定できません。すべてのリクエストは指定したプロキシ・サーバーに送信されます。例1-76に、ポート80のプロキシ・アドレスproxy.example.comが指定されたSEM_MATCH問合せを示します。

例1-75 UTL_HTTP.SET_PROXYでのプロキシ・サーバーの設定

BEGIN
  UTL_HTTP.SET_PROXY('proxy.example.com:80', 'example2.com');
END;
/

例1-76 SPARQL SERVICEでのプロキシ・サーバーの設定

SELECT *
  FROM TABLE(SEM_MATCH(
    'SELECT *
     WHERE {
       SERVICE <http://www.example1.org/sparql>{ ?s ?p ?o }
      }',
    SEM_Models('electronics'),
    null, null, null, null, ' SERVICE_PROXY=proxy.example.com:80 ', 
    null, null,
    'RDFUSER', 'NET1'));
1.6.8.5 HTTP基本認証でのSPARQLエンドポイントへのアクセス

HTTP基本認証でSPARQLエンドポイントへのアクセスを許可するには、ユーザー資格証明をセッション・コンテキストSDO_SEM_HTTP_CTXに保存する必要があります。DBA権限を持つユーザーが、基本認証の使用を希望するユーザーにこのコンテキストのEXECUTEを付与する必要があります。次の例では、このアクセス権をRDFUSERというユーザーに付与しています。

grant execute on mdsys.sdo_sem_http_ctx to rdfuser;

権限が付与されると、ユーザーは各SPARQLエンドポイントのユーザー名とパスワードをHTTP認証に保存する必要があります。これには、関数mdsys.sdo_sem_http_ctx.set_usrおよびmdsys.sdo_sem_http_ctx.set_pwdを使用します。次の例では、SPARQLエンドポイント(http://www.example1.org/sparql)のユーザー名とパスワードが設定されます。

BEGIN
  mdsys.sdo_sem_http_ctx.set_usr('http://www.example1.org/sparql','user');
  mdsys.sdo_sem_http_ctx.set_pwd('http://www.example1.org/sparql','pwrd');
END;
/

1.6.9 インライン問合せオプティマイザ・ヒント

SEM_MATCHでは、HINT0インライン問合せオプティマイザ・ヒントを許可するために、SPARQLコメント構成要素がオーバーロードされています。SPARQLのハッシュ(#)文字は、行のそれ以降の部分がコメントであることを示します。インライン・ヒントを特定のBGPと関連付けるには、HINT0ヒント文字列をSPARQLコメント内に配置し、開始中カッコ({)とBGPの最初のトリプル・パターンの間にコメントを挿入します。インライン・ヒントを使用すると、問合せ内の各BGPの実行計画に影響を与えることができます。

インライン・オプティマイザ・ヒントは、options引数を使用してSEM_MATCHに渡されるすべてのヒントをオーバーライドします。たとえば、インライン・オプティマイザ・ヒントを指定していない各BGPには、グローバルALL_ORDEREDヒントが適用されますが、インライン・ヒントを持つBGPには、ALL_ORDEREDヒントではなくインライン・ヒントが使用されます。

例1-77 インライン問合せオプティマイザ・ヒント (BGP_JOIN)

次の例は、インライン問合せオプティマイザ・ヒントを含む問合せです。

SELECT x, y, hp, cp
  FROM TABLE(SEM_MATCH(
    '{ # HINT0={ LEADING(t0) USE_NL(?x ?y ?bd) }
      ?x :grandParentOf ?y . ?x rdf:type :Male . ?x :birthDate ?bd
      OPTIONAL { # HINT0={ LEADING(t0 t1) BGP_JOIN(USE_HASH) }
                 ?x :homepage ?hp . ?x :cellPhoneNum ?cp }
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

BGP_JOINヒントはBGP結合間に影響を与えるもので、BGP_JOIN(<join_type>)という構文を使用します(<join_type>はUSE_HASHまたはUSE_NLです)。例1-77では、BGP_JOIN(USE_HASH)ヒントを使用して、OPTIONAL BGPをその親BGPと結合する場合にハッシュ結合を使用する必要があることを指定しています。

インライン・オプティマイザ・ヒントは、options引数を使用してSEM_MATCHに渡されるすべてのヒントをオーバーライドします。たとえば、インライン・オプティマイザ・ヒントを指定していない各BGPには、グローバルALL_ORDEREDヒントが適用されますが、インライン・ヒントを持つBGPには、ALL_ORDEREDヒントではなくインライン・ヒントが使用されます。

例1-78 インライン問合せオプティマイザ・ヒント (ANTI_JOIN)

ANTI_JOINヒントは、NOT EXISTS句およびMINUS句の評価に影響を与えます。このヒントは、ANTI_JOIN(<join_type>)という構文で使用されます。ここで、<join_type>はHASH_AJ, NL_AJまたはMERGE_AJです。次の例では、ハッシュ非結合を使用するよう指定するヒントが使用されています。グローバルのALL_AJ_HASH、ALL_AJ_NL、ALL_AJ_MERGEをSEM_MATCHのオプション引数に使用して、問合せ全体で、すべてのNOT EXISTS句およびMINUS句に影響を与えることができます。

SELECT x, y
  FROM TABLE(SEM_MATCH(
    'SELECT ?x ?y
     WHERE {
       ?x :grandParentOf ?y . ?x rdf:type :Male . ?x :birthDate ?bd
       FILTER ( 
         NOT EXISTS {# HINT0={ ANTI_JOIN(HASH_AJ) }
                     ?x :homepage ?hp . ?x :cellPhoneNum ?cp })
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

例1-79 インライン問合せオプティマイザ・ヒント(NON_NULL)

SPARQL SELECT句では、特定の変数が常にバインドされている(つまり結果の各行にはNULLでない値が含まれている)ことを示すHINT0={ NON_NULL}がサポートされています。このヒントにより、SELECTで生成された値に対する結合を問合せコンパイラで最適化できます。考えられるすべてのインプットに対して、式がNULLでない値を生成するとは限らないため、こうした最適化をデフォルトで適用することはできません。SELECT式でNULL値が生成されないことがわかっている場合には、NON_NULLヒントを使用することで、パフォーマンスが著しく向上します。このヒントは、SELECT式の「AS」キーワードの前に行のコメントで指定します。

次の例では、NON_NULLヒント・オプションがSEM_MATCH問合せで使用されており、?full_nameが必ずバインドされていることが明示されています。

SELECT s, t
  FROM TABLE(SEM_MATCH(
    'SELECT * WHERE {
       ?s :name ?full_name
       { SELECT (CONCAT(?fname, " ", ?lname) # HINT0={ NON_NULL }
                 AS ?full_name)
         WHERE { 
           ?t :fname ?fname .
           ?t :lname ?lname } 
         } 
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

1.6.10 全文検索

Oracle固有のorardf:textContains SPARQL FILTER関数は、RDF_VALUE$表で全文索引を使用します。この関数は次の構文を使用します(orardf<http://xmlns.oracle.com/rdf/>に展開される組込みの接頭辞です)。

orardf:textContains(variable, pattern)

orardf:textContainsへの最初の引数はローカル変数(つまり、orardf:textContainsフィルタを含むBGPに存在する変数)である必要があり、2つ目の引数は一定のプレーン・リテラルである必要があります。

たとえば、orardf:textContains(x, y)は、xが式yと一致する場合にtrueを戻します(yはOracle Text SQL演算子CONTAINSの有効な式です)。そのような式の詳細は、『Oracle Textリファレンス』を参照してください。

orardf:textContainsを使用する前に、RDFネットワークのOracle Text索引を作成する必要があります。そのような索引を作成するには、SEM_APIS.ADD_DATATYPE_INDEXプロシージャを次のように起動します。

EXECUTE SEM_APIS.ADD_DATATYPE_INDEX('http://xmlns.oracle.com/rdf/text', network_owner=>'RDFUSER', network_name=>'NET1');

orardf:textContains(?x, "%abc%")のようなワイルドカード検索のパフォーマンスは、プリフィックス索引と部分文字列索引を使用することで向上します。プリフィックス索引と部分文字列索引の設定を制御するために、次のいずれかのオプションをSEM_APIS.ADD_DATATYPE_INDEXプロシージャに含めることができます。

  • prefix_index=true: プリフィックス索引の追加

  • prefix_min_length=<number>: プリフィックス索引トークンの最小長さ

  • prefix_max_length=<number>: プリフィックス索引トークンの最大長さ

  • substring_index=true: 部分文字列索引の追加

Oracle Textの索引付け要素の詳細は、『Oracle Textリファレンス』を参照してください。

値-サブセット・テキスト(VST)索引を使用すると、SPARQL問合せの全体的なテキスト索引のパフォーマンスを向上させることができます。RDFネットワーク内のすべてのRDF語句はデフォルトでテキスト索引に含まれますが、VST索引では索引付けされた値を次のいずれかに制限します。
  • プレーンおよびxsd:string RDFリテラル
  • 入力包含リストに表示される述語を持つトリプルのオブジェクト値

VST索引に含まれる値が少なくなるため、テキスト索引が小さくなり、パフォーマンスも向上します。VST索引設定を制御するために、次のいずれかのオプションをSEM_APIS.ADD_DATATYPE_INDEXプロシージャに含めることができます。

  • PREDLIST=(<predicate1> <predicate2> … <predicateN>): オブジェクト値を索引付けする述語のリスト。周囲の山カッコを含む完全なIRI参照、またはPREFIXES=()からのネームスペース接頭辞を使用した接頭辞付きの名前で指定されます(たとえば、PREDLIST=(<http://example.com/predicate1> ex:predicate2))。
  • PREFIXES=(<SPARQL_prefix1> <SPARQL_prefix2> … <SPARQL_prefixN>): 接頭辞付きの名前をPREDLIST=()で展開するときに使用する接頭辞のリスト。SPARQL構文を使用して指定します(たとえば、PREFIXES=(PREFIX ex: <http://example.com/> PREFIX ex2: <http://example2.com>))。
  • STRING_LITERALS_ONLY=T: 指定すると、文字列リテラルRDF語句のみが索引付けされます。PREDLISTベースのオプションも指定されている場合、これは使用できません。

テキスト索引のあるセマンティク・ネットワークに対して大規模バルク・ロードを実行する場合、テキスト索引を削除してバルク・ロードを実行してからテキスト索引を再作成すると、ロード時間全体が短縮される可能性があります。データ型索引の詳細は、「データ型索引の使用」を参照してください。

テキスト索引を作成すると、SEM_MATCH問合せでorardf:textContains FILTER関数を使用できます。例1-80では、orardf:textContainsを使用して、名前が文字AまたはBで始まるすべての祖父を検索しています。

例1-80 全文検索

SELECT x, y, n
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/>
     SELECT * 
     WHERE { 
       ?x :grandParentOf ?y . ?x rdf:type :Male . ?x :name ?n 
       FILTER (orardf:textContains(?n, " A% | B% ")) }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null, null, null, ' ', null, null,
   'RDFUSER', 'NET1'));

例1-81 orardf:textScore

副演算子orardf:textScoreorardf:textContainsと組み合わせて使用することで、結果をテキスト一致の程度でランク付けできます。ただし、orardf:textScoreの使用には制限があります。orardf:textScore呼び出しは、対応するorardf:textContains FILTERを含んでいる基本のグラフ・パターンの、すぐ外側にあるSELECT句のSELECT式として記述されている必要があります。その後は、このSELECT式の別名を、問合せの他の箇所で使用することができます。さらに、REWRITE=F問合せヒントを、SEM_MATCHのoptions引数で使用する必要があります。

次の例では、スコアが0.5を超えるテキスト一致を探しています。ここで、orardf:textContainsには呼出しIDを付加して、同じ呼出しIDを持つorardf:textScore呼出しと結び付けられるようにする必要があることに注意してください。呼び出しIDは任意の整数であり、主演算子をその副演算子と照合するために使用されます。

SELECT x, y, n, scr
  FROM TABLE(SEM_MATCH(
    'PREFIX <http://www.example.org/family/>
     SELECT *
     WHERE {
       { SELECT ?x ?y ?n (orardf:textScore(123) AS ?scr)
         WHERE { 
           ?x :grandParentOf ?y . ?x rdf:type :Male . ?x :name ?n 
           FILTER (orardf:textContains(?n, " A% | B% ", 123)) }
       }
       FILTER (?scr > 0.5)
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null,           
    null,
    null,
    ' REWRITE=F ', 
    null, null,
    'RDFUSER', 'NET1'));

例1-82 orardf:like

負荷が大きくないテキスト検索では、orardf:like関数を使用することができます。その場合、Oracle SQLのLIKE演算子を使用した単純なテストパターン照合が行われます。orardf:like関数の構文は次のとおりです。

orardf:like(string, pattern)

orardf:likeの最初の引数には任意の変数またはRDF語句を指定できます。それに対してorardf:Containsの最初の引数はローカル変数でなければなりません。orardf:likeの最初の引数がURIである場合、照合はURIの接尾辞のみを対象にして行われます。2つ目の引数にはパターン式を指定する必要があります。このとき、次の特殊パターン一致文字を含めることができます。

  • パーセント記号(%)は0個以上の文字を表します。

  • アンダースコアはちょうど1文字を表します。

次の例では、パーセント記号(%)をワイルドカードとして使用して、URIがJaで始まるすべての祖父母を検索しています。

SELECT x, y, n
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/>
     SELECT * 
     WHERE { 
        ?x :grandParentOf ?y . ?y :name ?n 
        FILTER (orardf:like(?x, "Ja%")) }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

次の例では、アンダースコア(_)をワイルドカードとして使用して、名前がJで始まり、その後に2文字が続いてkで終わる、すべての孫を検索しています。

SELECT x, y, n
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/>
     SELECT * 
     WHERE { 
        ?x :grandParentOf ?y . ?y :name ?n 
        FILTER (orardf:like(?n, "J__k")) 
    }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    
    null, null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

orardf:likeの実行効率を高めるために、SEM_APIS.ADD_DATATYPE_INDEXプロシージャを使用し、http://xmlns.oracle.com/rdf/likeをデータ型URIとして、索引を作成できます。この索引によって、最初の引数がローカル変数で、かつ検索パターンの前にある文字がワイルドカードでない場合に、問合せを高速化することができます。ここで基礎となっている索引は、VARCHAR型関数に対する単純な関数ベースのBツリー索引であるため、完全なOracle Text索引よりも保守とストレージに要するコストが低く抑えられます。orardf:likeは、次のようにして作成します。

EXECUTE SEM_APIS.ADD_DATATYPE_INDEX('http://xmlns.oracle.com/rdf/like');

1.6.11 空間のサポート

RDFセマンティク・グラフは、OGC GeoSPARQL標準を介して、およびOracle固有のSPARQL拡張機能を介して空間ジオメトリ・データの記憶域および問合せをサポートしています。ジオメトリ・データはorageo:WKTLiteralogc:wktLiteralまたはogc:gmlLiteral型付きリテラルとして格納可能で、空間操作用のいくつかの問合せ関数を使用してジオメトリ・データを問い合せることができます。パフォーマンス向上のための空間索引付けも、サポートされます。

orageo<http://xmlns.oracle.com/rdf/geo/>に展開される組込み接頭辞、ogc<http://www.opengis.net/ont/geosparql#>に展開される組込み接頭辞、ogcf<http://www.opengis.net/def/function/geosparql>に展開される組込み接頭辞です。

1.6.11.1 OGC GeoSPARQLのサポート

RDFセマンティク・グラフは、Well-Known Text (WKT)シリアライズとシンプル・フィーチャのリレーション・ファミリを使用して、OGC GeoSPARQL標準(http://www.opengeospatial.org/standards/geosparql)に準拠する次のクラスをサポートします。

  • コア

  • トポロジ・ボキャブラリ拡張(シンプル・フィーチャ)

  • ジオメトリ拡張(WKT、1.2.0)

  • ジオメトリ・トポロジ拡張(シンプル・フィーチャ、WKT、1.2.0)

  • RDFS伴意拡張(シンプル・フィーチャ、WKT、1.2.0)

さらに、RDFセマンティク・グラフは、地理マークアップ言語(GML)シリアライズおよびシンプル・フィーチャのリレーション・ファミリを使用して、OGC GeoSPARQLに準拠する次のクラスをサポートします。

  • コア

  • トポロジ・ボキャブラリ拡張(シンプル・フィーチャ)

  • ジオメトリ拡張(GML、3.1.1)

  • ジオメトリ・トポロジ拡張(シンプル・フィーチャ、GML、3.1.1)

  • RDFS伴意拡張(シンプル・フィーチャ、GML、3.1.1)

GeoSPARQLを使用した空間データの表現および問合せの詳細は、以降の項で説明します。

1.6.11.2 RDFでの空間データの表現

空間ジオメトリは、RDFでorageo:WKTLiteralogc:wktLiteralまたはogc:gmlLiteral型付きリテラルとして表現できます。

例1-83 orageo:WKTLiteralとして表現される空間点ジオメトリ

次の例では、単純な点ジオメトリのorageo:WKTLiteralエンコーディングを示します。

"Point(-83.4 34.3)"^^<http://xmlns.oracle.com/rdf/geo/WKTLiteral>

例1-84 ogc:wktLiteralとして表現される空間点ジオメトリ

次の例では、前の例と同じ点のogc:wktLiteralエンコーディングを示します。

"Point(-83.4 34.3)"^^<http://www.opengis.net/ont/geosparql#wktLiteral>

orageo:WKTLiteralogc:wktLiteralエンコーディングはどちらも、オプションの空間参照システムURIと、それに続くWell-Known Text(WKT)文字列(ジオメトリ値をエンコードする)で構成されます。空間参照システムURIとWKT文字列は、空白文字で分離する必要があります。(このドキュメントでは、ジオメトリ・リテラルという用語で、orageo:WKTLiteralogc:wktLiteral型付きリテラルの両方を指しています。)

サポートされる空間参照システムURIは、<http://www.opengis.net/def/crs/EPSG/0/{srid}>という形式を取ります({srid}は、European Petroleum Survey Group (EPSG)によって定義される有効な空間参照システムIDです)。EPSGジオメトリック・パラメータ・データセットに含まれないURIの場合、使用される空間参照システムURIは、<http://xmlns.oracle.com/rdf/geo/srid/{srid}>という形式を取ります({srid}は、Oracle Spatial and Graphの有効な空間参照システムIDです)。ジオメトリ・リテラル値に空間参照システムURIが含まれない場合、デフォルトの空間参照システムのWGS84経度-緯度(URI <http://www.opengis.net/def/crs/OGC/1.3/CRS84>)が使用されます。問合せ文字列内にジオメトリ・リテラル値が見つかると、同じデフォルトの空間参照システムが使用されます。

例1-85 ogc:gmlLiteralとして表現される空間点ジオメトリ

次の例では、点ジオメトリのogc:gmlLiteralエンコーディングを示します。

"<gml:Point srsName=\"urn:ogc:def:crs:EPSG::8307\" xmlns:gml=\"http://www.opengis.net/gml\"><gml:posList srsDimension=\"2\">-83.4 34.3</gml:posList></gml:Point>"^^<http://www.opengis.net/ont/geosparql#gmlLiteral>

ogc:gmlLiteralエンコーディングは、GM_Objectのサブタイプを実装するGMLスキーマの有効な要素で構成されます。WKTリテラルとは異なり、GMLエンコーディングには空間参照システム情報が明示的に含まれるため、空間参照システムURIの接頭辞が不要です。

いくつかのジオメトリ・タイプは、点、線ストリング、ポリゴン、多面体面、三角形、TIN、複数点、複数の線ストリング、複数のポリゴンおよびジオメトリ・コレクションを含む、ジオメトリ・リテラル値として表現できます。2次元ジオメトリでは、1ジオメトリ当たり最大500,000の頂点がサポートされます。

例1-86 orageo:WKTLiteral値を使用してエンコードされる空間データ

次の例では、orageo:WKTLiteral値を使用してエンコードされるRDF空間データ(N-triple形式)をいくつか示します。この例では、最初の2つのジオメトリ(lot1内)はデフォルトの座標系(SRID 8307)を使用し、その他の2つのジオメトリ(lot2内)はSRID 8265を指定しています。

# spatial data for lot1 using the default WGS84 Longitude-Latitude spatial reference system
<urn:lot1> <urn:hasExactGeometry> "Polygon((-83.6 34.1, -83.6 34.5, -83.2 34.5, -83.2 34.1, -83.6 34.1))"^^<http://xmlns.oracle.com/rdf/geo/WKTLiteral> .
<urn:lot1> <urn:hasPointGeometry> "Point(-83.4 34.3)"^^<http://xmlns.oracle.com/rdf/geo/WKTLiteral> .
# spatial data for lot2 using the NAD83 Longitude-Latitude spatial reference system
<urn:lot2> <urn:hasExactGeometry> "<http://xmlns.oracle.com/rdf/geo/srid/8265> Polygon((-83.6  34.1, -83.6 34.3, -83.4 34.3, -83.4 34.1, -83.6 34.1))"^^<http://xmlns.oracle.com/rdf/geo/WKTLiteral> .
<urn:lot2> <urn:hasPointGeometry> "<http://xmlns.oracle.com/rdf/geo/srid/8265> Point(-83.5 34.2)"^^<http://xmlns.oracle.com/rdf/geo/WKTLiteral> .

詳細は、『Oracle Spatial and Graph開発者ガイド』の座標系(空間参照システム)に関する章を参照してください。Open Geospatial Consortium (OGC)のシンプル・フィーチャのドキュメント(http://www.opengeospatial.org/standards/sfa)で、WKTジオメトリ表現に関する資料も参照してください。

1.6.11.3 ジオメトリの検証

空間データを操作する前に、RDFモデルに無効なジオメトリ・リテラルが格納されていないことを確認する必要があります。プロシージャSEM_APIS.VALIDATE_GEOMETRIESを使用すると、RDFモデルのジオメトリを検証できます。ジオメトリは、入力SRIDおよび許容値を使用して検証します。(SRIDおよび許容値の詳細は、「空間データの索引付け」を参照してください。)

無効なジオメトリが存在する場合、{model_name}_IVG$という名前の表がユーザー・スキーマに作成されます({model_name}は指定したRDFモデルの名前です)。このような表には、無効なジオメトリ・リテラルごとに、RDF_VALUE$表のジオメトリ・リテラルのvalue_id、ジオメトリが有効でない理由を説明するエラー・メッセージおよびジオメトリが修正できる場合は修正されたジオメトリ・リテラルが含まれます。ジオメトリの検証の詳細は、Oracle Spatial and GraphサブプログラムSDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXTおよびSDO_GEOM.VALIDATE_LAYER_WITH_CONTEXTのリファレンス情報を参照してください。

例1-87 モデルのジオメトリの検証

次の例では、SRID=8307およびtolerance=0.1を使用してモデルmを検証します。

-- Validate
EXECUTE sem_apis.validate_geometries(model_name=>'m',SRID=>8307,tolerance=>0.1, network_owner=>'RDFUSER', network_name=>'NET1');-- Check for invalid geometries
SELECT original_vid, error_msg, corrected_wkt_literal FROM M_IVG$;
1.6.11.4 空間データの索引付け

任意のSPARQL拡張関数(「空間データの問合せ」を参照)を使用して空間データを問い合せる前に、SEM_APIS.ADD_DATATYPE_INDEXプロシージャをコールしてRDFネットワークに空間索引を作成する必要があります。

空間索引を作成する場合、次の情報を指定する必要があります。

  • SRID - 空間索引を作成する空間参照システムのID。Oracle Spatial and Graphからの任意の有効な空間参照システムIDを、SRID値として使用できます。

  • TOLERANCE: 空間索引の許容値。許容値は、2つの点が同じ点とみなされるためにどの程度近接している必要があるかを示す正数です。この値の単位は、使用されるSRIDのデフォルト単位によって決定されます(たとえば、WGS84経度/緯度の場合はメートル)。許容差は、『Oracle Spatial and Graph開発者ガイド』で詳細に説明されています。

  • DIMENSIONS - 空間索引のテキスト文字列エンコーディングの次元情報。各次元は、カンマ区切りの一連の3つの値(名前、最小値および最大値)で表現されます。各次元をカッコで囲み、それらの次元のセットを外側のカッコで囲みます。

例1-88 RDFデータ上の空間データ型索引の追加

例1-88では、RDFネットワーク上の空間データ型索引を追加し、この座標系を使用する空間データの索引付けに関する、WGS84経度-緯度空間参照システム、0.1の許容値、推奨次元を指定しています。TOLERANCE、SRIDおよびDIMENSIONSキーワードの大/小文字は区別され、<http://xmlns.oracle.com/rdf/geo/WKTLiteral>に対してデータ型索引を作成すると、<http://www.opengis.net/ont/geosparql#wktLiteral>ジオメトリ・リテラルにも索引付けされ、この逆も同様に行われます(つまり、<http://www.opengis.net/ont/geosparql#wktLiteral>に対してデータ型索引を作成すると<http://xmlns.oracle.com/rdf/geo/WKTLiteral>ジオメトリ・リテラルにも索引付けされます)。

EXECUTE sem_apis.add_datatype_index('http://xmlns.oracle.com/rdf/geo/WKTLiteral',  options=>'TOLERANCE=10 SRID=8307 DIMENSIONS=((LONGITUDE,-180,180) (LATITUDE,-90,90))', network_owner=>'RDFUSER', network_name=>'NET1');

RDFネットワークについては1つの空間データ型索引のみサポートされます。RDFネットワークに格納されるジオメトリ・リテラル値は、索引に使用される空間参照システムに自動的に正規化されるため、単一の空間索引では複数の空間参照システムからのジオメトリ・リテラル値を同時にサポートできます。この座標変換は、索引付けと空間の計算に対して透過的に行われます。ジオメトリ・リテラル値がSEM_MATCH問合せから戻されるときは、元の未変換のジオメトリが戻されます。

空間索引付けの詳細は、『Oracle Spatial and Graph開発者ガイド』で空間データの索引付けおよび問合せに関する章を参照してください。

例1-89 RDFデータでの空間データ型の実体化された索引の追加

空間データを操作する際、ジオメトリ・リテラルからジオメトリ・オブジェクトへの変換が必要になる場合がありますが、変換によってはパフォーマンスが低下することがあります。このような状況を回避するため、格納されているすべてのジオメトリ・リテラルを、索引の作成時にSDO_GEOMETRYオブジェクトに変換して実体化できます。

これは、空間データ型索引の追加時にMATERIALIZE=Tオプションを使用すると実現できます。索引付けするジオメトリ・リテラルの量が大量の場合は、オプションINS_AS_SEL=Tを使用すると、実体化された索引の作成の高速化に役立つことがあります。

次の例に、実体化された空間索引の作成を示します。

EXECUTE sem_apis.add_datatype_index('http://xmlns.oracle.com/rdf/geo/WKTLiteral',  options=>'TOLERANCE=0.1 SRID=8307 DIMENSIONS=((LONGITUDE,-180,180) (LATITUDE,-90,90)) MATERIALIZE=T ');

例1-90 RDFデータでの3D空間データ型索引の追加

Oracle Spatial and Graphでは、3つの座標を持つ空間索引を作成できます。3D索引を作成するには、SEM_APIS.ADD_DATATYPE_INDEXプロシージャのoptions引数でSDO_INDX_DIMS=3オプションを指定する必要があります。

次の例に、3Dデータの作成および索引付けを示します。座標は(X, Y, Z)の順に指定され、外側のポリゴン境界の線形の輪は反時計回りに指定されていることに注意してください。

ノート: 制限を含め、3Dデータでのジオメトリ操作のサポートの詳細は、3次元空間オブジェクトに関する項を参照してください。

conn rdfuser/<password>;

create table geo3d_tab(tri sdo_rdf_triple_s);

exec sem_apis.create_sem_model('geo3d','geo3d_tab','tri');

-- 3D Polygon
insert into geo3d_tab(tri) values(sdo_rdf_triple_s('geo3d','<http://example.org/ApplicationSchema#A>', '<http://example.org/ApplicationSchema#hasExactGeometry>', '<http://example.org/ApplicationSchema#AExactGeom>'));
insert into geo3d_tab(tri) values(sdo_rdf_triple_s('geo3d','<http://example.org/ApplicationSchema#AExactGeom>', '<http://www.opengis.net/ont/geosparql#asWKT>', '"<http://xmlns.oracle.com/rdf/geo/srid/31468> Polygon ((4467504.578 5333958.396 513.9, 4467508.939 5333956.379 513.9, 4467509.736 5333958.101 513.9, 4467505.374 5333960.118 513.9, 4467504.578 5333958.396 513.9))"^^<http://xmlns.oracle.com/rdf/geo/WKTLiteral>'));

-- 3D Point at same elevation as Polygon
insert into geo3d_tab(tri) values(sdo_rdf_triple_s('geo3d','<http://example.org/ApplicationSchema#B>', '<http://example.org/ApplicationSchema#hasExactGeometry>', '<http://example.org/ApplicationSchema#BExactGeom>'));
insert into geo3d_tab(tri) values(sdo_rdf_triple_s('geo3d','<http://example.org/ApplicationSchema#BExactGeom>', '<http://www.opengis.net/ont/geosparql#asWKT>', '"<http://xmlns.oracle.com/rdf/geo/srid/31468> Point (4467505.000 5333959.000 513.9)"^^<http://xmlns.oracle.com/rdf/geo/WKTLiteral>'));

-- 3D Point at different elevation from Polygon
insert into geo3d_tab(tri) values(sdo_rdf_triple_s('geo3d','<http://example.org/ApplicationSchema#C>', '<http://example.org/ApplicationSchema#hasExactGeometry>', '<http://example.org/ApplicationSchema#CExactGeom>'));
insert into geo3d_tab(tri) values(sdo_rdf_triple_s('geo3d','<http://example.org/ApplicationSchema#CExactGeom>', '<http://www.opengis.net/ont/geosparql#asWKT>', '"<http://xmlns.oracle.com/rdf/geo/srid/31468> Point (4467505.000 5333959.000 13.9)"^^<http://xmlns.oracle.com/rdf/geo/WKTLiteral>'));
commit;

-- Create 3D index
conn system/manager;
exec sem_apis.add_datatype_index('http://xmlns.oracle.com/rdf/geo/WKTLiteral' ,options=>'TOLERANCE=0.1 SRID=3148 DIMENSIONS=((x,4386596.4101,4613610.5843) (y,5237914.5325,6104496.9694) (z,0,10000)) SDO_INDX_DIMS=3 ');

conn rdfuser/rdfuser;
-- Find geometries within 200 M of my:A
-- Returns only one point because of 3D index
SELECT aGeom, f, fGeom, aWKT, fWKT
FROM TABLE(SEM_MATCH(
 '{ my:A my:hasExactGeometry ?aGeom .
     ?aGeom ogc:asWKT ?aWKT .
     ?f my:hasExactGeometry ?fGeom .
     ?fGeom ogc:asWKT ?fWKT .
     FILTER (orageo:withinDistance(?aWKT, ?fWKT,200,"M") &&
             !sameTerm(?aGeom,?fGeom))
   }',
 SEM_Models('geo3d'),
 null,
 SEM_ALIASES(
  SEM_ALIAS('my','http://example.org/ApplicationSchema#')),
 null));
1.6.11.5 空間データの問合せ

SEM_MATCHで空間問合せを実行するために、複数のSPARQL拡張関数を使用できます。たとえば、空間RDFデータでは、ジオメトリの領域と境界線(長さ)、2つのジオメトリ間の距離、およびジオメトリの重心と最小外接矩形を検出することや、ジオメトリ間の様々な位相関係を確認することができます。

「空間問合せのSEM_MATCHサポート」には、次を含めて使用可能な関数のリファレンスおよび使用方法に関する情報が記載されています。

  • GeoSPARQLの関数

  • Oracle固有の関数

1.6.11.6 GeoSPARQL問合せとのロング・リテラルの使用

ジオメトリ・リテラルは非常に長くなることがあり、それらを表すのにCLOBの使用が必要になります。CLOB定数は、SEM_MATCH問合せで直接使用することはできません。しかし、ユーザー定義のSPARQL関数を使用してCLOB定数をSEM_MATCH問合せにバインドできます。

次の例では、一時表を使用してこれを行っています。

例1-91 SPARQL問合せへのCLOB定数のバインド

conn rdfuser/<password>;

-- Create temporary table
create global temporary table local_value$(
 VALUE_TYPE 	 VARCHAR2(10),
 VALUE_NAME     VARCHAR2(4000),
 LITERAL_TYPE	 VARCHAR2(1000),
 LANGUAGE_TYPE	 VARCHAR2(80),
 LONG_VALUE 	 CLOB)
on commit preserve rows;

-- Create user-defined function to transform a CLOB into an RDF term
CREATE OR REPLACE FUNCTION myGetClobTerm
RETURN MDSYS.SDO_RDF_TERM
AS
  term	     SDO_RDF_TERM;
BEGIN
  select sdo_rdf_term(
      value_type,
      value_name,
      literal_type,
      language_type,
      long_value)
  into term
  from local_value$
  where rownum < 2;

  RETURN term;
END;
/

-- Insert a row with CLOB geometry
insert into local_value$(value_type,value_name,literal_type,language_type,long_value)
values ('LIT','','http://www.opengis.net/ont/geosparql#wktLiteral','','Some_CLOB_WKT');

-- Use the CLOB constant in a SEM_MATCH query
SELECT cdist
FROM table(sem_match(
'{ ?cdist ogc:asWKT ?cgeom 
   FILTER (
     orageo:withinDistance(?cgeom, oraextf:myGetClobTerm(), 200, "M")) }'
,sem_models('gov_all_vm')
,null, null, null, null, ' ALLOW_DUP=T ', null, null
,'RDFUSER', 'NET1'));

1.6.12 フラッシュバック問合せのサポート

フラッシュバック問合せを使用して、過去のデータを返すSEM_MATCH問合せを実行できます。TIMESTAMPまたはシステム変更番号(SCN)の値が、AS_OFヒントを介してSEM_MATCHへ渡されます。AS_OFヒントは、次のいずれかの書式で指定できます。

  • AS_OF[TIMESTAMP,<TIMESTAMP_VALUE>] (ここで、<TIMESTAMP_VALUE>は「YYYY/MM/DD HH24:MI:SS.FF」という形式の、有効なタイムスタンプ文字列です。)

  • AS_OF[SCN,<SCN_VALUE>] (ここで<SCN_VALUE>は有効なSCNです。)

AS_OFヒントは、指定したモデルのトリプルを格納している問合せ対象の表またはビューに対してフラッシュバック問合せ(SELECT AS OF)を実行するために、内部変換されます。これにより、それ以前に存在していたモデルに対する問合せが可能になります。この機能を動作させるには、呼出しの際に、問合せの対象となるメタデータの表またはビューに対するフラッシュバック権限が必要です(ネイティブ・モデルに対するRDFM_model-nameビュー、仮想モデルに対するSEMU_virtual-model-nameおよびSEMV_virtual-model-name、およびRDFビュー・モデルの基礎となっているリレーショナル表)。たとえば: grant flashback on RDFUSER.NET1#RDFM_FAMILY to scott

RDFデータでフラッシュバック問合せを使用する際の制限

パーティション表に対して、パーティションの追加や削除を行うと、以前のバージョンのパーティション表に対するフラッシュバック問合せが無効化されます。結果的に、ネイティブRDFモデルの作成または削除、あるいは伴意の作成または削除により、セマンティク・ネットワークにある以前のバージョンのネイティブRDFモデルすべてに対するフラッシュバック問合せが無効になります。したがって、セマンティク・ネットワークでフラッシュバック問合せを使用している場合、そうした操作は確実に管理する必要があります。

例1-92 TIMESTAMPを使用したフラッシュバック問合せ

次の例では、AS_OF句を使用してTIMESTAMPを定義しています。

SELECT x, name
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/>
     SELECT * 
     WHERE { ?x :name ?name }',
    SEM_Models('family'),
    null, null,
    null,null,' AS_OF=[TIMESTAMP,2016/05/02 13:06:03.979546]', 
    null, null,
    'RDFUSER', 'NET1'));

例1-93 SCNを使用したフラッシュバック問合せ

次の例では、AS_OF句を使用してSCNを指定しています。

SELECT x, name
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/>
     SELECT * 
     WHERE { ?x :name ?name }',
    SEM_Models('family'),
    null, null,
    null,null,' AS_OF=[SCN,1429849]', 
    null, null,
    'RDFUSER', 'NET1'));

1.6.13 SPM補助表を使用した問合せ実行の高速化

ノート:

Subject-Property-Matrix補助表を使用するには、次のデータベース・パッチを使用する必要があります。

パッチ33806152: データベース・リリース更新19.15.0.0.0

このパッチは、現在My Oracle Supportで入手でき、19cのどのリリースにもインストールできます。

Subject-Property-Matrix (SPM)補助表を使用すると、SPARQL問合せの実行を高速化できます。

特定のモデルのSPM補助表のセットには、ゼロ個以上の単一値プロパティ(SVP)表、ゼロ個以上の複数値プロパティ(MVP)表およびゼロ個以上のプロパティ・チェーン(PCN)表が含まれます。SVPおよびPCN表は結合を減らすことで問合せの実行を高速化し、MVP表は問合せオプティマイザ統計および問合せ計画を改善できるようにすることで問合せの実行を高速化します。

1.6.13.1 単一値プロパティ表

単一値プロパティ(SVP)表には、単一値RDFプロパティの値が保持されます。

モデル内の各リソースがpに最大で1つの値を持つ場合、プロパティpはRDFモデル内の単一値です。たとえば、:date_of_birthなどのプロパティは単一値になる傾向がありますが、:friend_ofなどのプロパティは複数値になる傾向があります。RDFプロパティのセットに対して作成されたSVP表は、各サブジェクト・リソースの単一行にこれらのプロパティの値を保持します。これにより、RDF_LINK$表の複数の自己結合ではなく、単一の表参照を使用してリソースの複数のプロパティを取得できます。デフォルトでは、各プロパティ値のIDのみが格納されます。SVP表は、次のような「スター・パターン」問合せの速度を大幅に向上させます。

SELECT ?s ?fname ?lname ?height ?ssn
 WHERE {
      ?s :first_name ?fname;
         :last_name ?lname;
         :date_of_birth ?height;
         :ssn ?ssn .
       }
SVP表には、次の2つのネーミング規則のいずれかを指定できます。
  • <NETWORK_NAME>#RDF_XT$SVP_<MODEL_NAME>: これはデフォルトのネーミング規則で、ユーザーがSVP表名を指定しない場合に使用されます。このデフォルト名を使用できるのは、モデルのSVP表の1つのみです。
  • <NETWORK_NAME>#RDF_XT$SVP_<MODEL_NAME>__<USER_SUPPLIED_NAME>: ユーザーがSVP表名を指定した場合に使用されます。

SVP表の列を次の表に示します。

表1-18 単一値表の列

列名 データ型 説明
START_NODE_ID NUMBER サブジェクト・リソースの値IDおよび表の主キー。
G<PREDICATE_ID_1> NUMBER 主語ID = START_NODE_IDで述語ID = PREDICATE_ID_1のトリプルを含む名前付きグラフの値ID。または、そのような名前付きグラフが存在しない場合はNULL
P<PREDICATE_ID_1> NUMBER 主語ID = START_NODE_IDおよび述語ID = PREDICATE_ID_1のトリプルのオブジェクトの値ID。または、そのようなトリプルが存在しない場合はNULL。
G<PREDICATE_ID_2> NUMBER 主語ID = START_NODE_IDで述語ID = PREDICATE_ID_2のトリプルを含む名前付きグラフの値ID。または、そのような名前付きグラフが存在しない場合はNULL
P<PREDICATE_ID_2> NUMBER 主語ID = START_NODE_IDおよび述語ID = PREDICATE_ID_2のトリプルのオブジェクトの値ID。または、そのようなトリプルが存在しない場合はNULL
G<PREDICATE_ID_n> NUMBER 主語ID = START_NODE_IDで述語ID = PREDICATE_ID_nのトリプルを含む名前付きグラフの値ID。または、そのような名前付きグラフが存在しない場合はNULL
P<PREDICATE_ID_n> NUMBER 主語ID = START_NODE_IDで述語ID = PREDICATE_ID_nのトリプルのオブジェクトの値ID。または、そのようなトリプルが存在しない場合はNULL

START_NODE_IDは主キーで、SVP表でカバーされる各述語には、名前付きグラフID (G<PREDICATE_ID>)の列とオブジェクトID (P<PREDICATE_ID)の列の、2つの列があります。

デフォルトでは、SVP表のSTART_NODE_ID列には、<NETWORK_NAME>#RDF_XX$SVP_<MODEL_NAME>_UQ__<USER_SUPPLIED_NAME>というネーミング規則を使用した一意索引があります。

1.6.13.2 複数値プロパティ表

複数値プロパティ(MVP)表には、複数値RDFプロパティの値が保持されます。

モデル(s p o1)(s p o2)に2つのトリプルが存在し、o1o2と等しくない場合、RDFモデルではプロパティpは複数値です。つまり、sには、プロパティpに対して複数の異なるオブジェクト値があります。複数値プロパティpのすべてのトリプルは同じMVP表に格納されるため、問合せオプティマイザはプロパティpに対してより正確な統計を取得できます。

MVP表のネーミング規則は、<NETWORK_NAME>#RDF_XT$MVP_<MODEL_NAME>_P<PREDICATE_ID>です。

MVP表の列を次の表に示します。

表1-19 複数値表の列

列名 データ型 説明
START_NODE_ID NUMBER サブジェクト・リソースの値ID。
G<PREDICATE_ID> NUMBER 主語ID = START_NODE_IDで述語ID = PREDICATE_IDのトリプルを含む名前付きグラフの値ID。または、そのような名前付きグラフが存在しない場合はNULL
P<PREDICATE_ID> NUMBER 主語ID = START_NODE_IDおよび述語ID = PREDICATE_IDであるトリプルのオブジェクトの値ID。

デフォルトでは、MVP表のSTART_NODE_ID列には、<NETWORK_NAME>#RDF_XX$MVP_<MODEL_NAME>_P<PREDICATE_ID>というネーミング規則を使用した一意でない索引があります。

1.6.13.3 プロパティ・チェーン表

プロパティ・チェーン(PCN)表はRDFグラフのパスを保持します。

i > 1の各tiについて、ti-1のオブジェクト値がtiの主語値と等しい場合、トリプルt1, t2, …, tnのセットがパスを形成します。PCN表は、ユーザー指定の順序またはプロパティURIのリストに基づいています。対応するPCN表の各行は、プロパティURIシーケンスに一致するトリプルのパスを表します。トリプルt1, t2,…,tnのパスは、iごとにtiの述語URIがpiと等しい場合、プロパティURI p1,p2,…,pnのシーケンスと一致します。PCN表を使用すると、RDF_LINK$の複数の目的語と主語の結合を使用するかわりに、SPARQL問合せ内のトリプル・パターンのパスを単一の表参照で評価できます。

たとえば、次の問合せの各結果は、RDF_LINK$の2つの自己結合を必要とするかわりに、(:hasAddress, :addrCityState, :addrCityのPCN表の単一行として検出できます。

SELECT ?s ?city   
 WHERE {
          ?s :hasAddress/:addrCityState/:addrCity ?city 
       }

PCN表のネーミング規則は、<NETWORK_NAME>#RDF_XT$PCN_<MODEL_NAME>__<USER_SUPPLIED_NAME>です。

次の表に、プロパティ・チェーン: (<PREDICATE_ID_1>, <PREDICATE_ID_2>, …, <PREDICATE_ID_n>)のPCN表の列を示します。

表1-20 プロパティ・チェーン表の列

列名 データ型 説明
START_NODE_ID NUMBER パスに含まれる最初のトリプルの主語の値ID。
G<PREDICATE_ID_1> NUMBER 主語ID = START_NODE_IDで述語ID = PREDICATE_ID_1のトリプルを含む名前付きグラフの値ID。または、そのような名前付きグラフが存在しない場合はNULL。
P<PREDICATE_ID_1> NUMBER 主語ID = START_NODE_IDおよび述語ID = PREDICATE_ID_1であるトリプルのオブジェクトの値ID。
G<PREDICATE_ID_2> NUMBER 主語ID = P<PREDICATE_ID_1>で述語ID = PREDICATE_ID_2のトリプルを含む名前付きグラフの値ID。または、そのような名前付きグラフが存在しない場合はNULL
P<PREDICATE_ID_2> NUMBER 主語ID = P<PREDICATE_ID_1>および述語ID = PREDICATE_ID_2のトリプルのオブジェクトの値ID。
G<PREDICATE_ID_n> NUMBER 主語ID = P<PREDICATE_ID_n-1>で述語ID = PREDICATE_ID_nのトリプルを含む名前付きグラフの値ID。または、そのような名前付きグラフが存在しない場合はNULL
P<PREDICATE_ID_n> NUMBER 主語ID = P<PREDICATE_ID_n-1>および述語ID = PREDICATE_ID_nのトリプルのオブジェクトの値ID。

デフォルトでは、PCN表のSTART_NODE_IDおよびすべてのP<PREDICATE_ID>列に一意でない索引があります。

索引のネーミング規則は、次のとおりです。
  • START_NODE_ID: <NETWORK_NAME>#RDF_XX$PCN_<MODEL_NAME>_UQ__<USER_SUPPLIED_NAME>
  • P<PREDICATE_ID>: <NETWORK_NAME>#RDF_XX$PCN_<MODEL_NAME>__<USER_SUPPLIED_NAME>_P<PREDICATE_ID>
1.6.13.4 SPM表の作成

SPM表は述語情報表に基づいて作成されます。この表には、モデル内の各述語に関する統計が記録されており、単一値の述語と複数値の述語を判別できます。

SEM_APIS.GATHER_SPM_INFOプロシージャを使用して、特定のモデルに対してこの表を作成し、データを移入できます。述語情報表には次の列があります。

表1-21 述語情報表の列

列名 タイプ 説明
P_VALUE_ID NUMBER 述語の値ID。
PRED_NAME NUMBER 述語の字句の値。
MIN_CNT NUMBER この述語に対してサブジェクト・リソースが持つ個別値の最小数。
MAX_CNT NUMBER この述語に対してサブジェクト・リソースが持つ個別値の最大数。
MED_CNT NUMBER この述語に対してサブジェクト・リソースが持つ個別値の中央値。
AVG_CNT NUMBER この述語に対してサブジェクト・リソースが持つ個別値の平均数。
TOT_CNT NUMBER この述語を含むトリプルの合計数。
INCLUDE VARCHAR2(30) SVP表に述語を含めない場合は'N'。述語をSVP表に含める必要がある場合は、'Y'またはNULL。述語をSVP表に含める必要があり、その目的語の字句値コンポーネントも含める必要がある場合は'V'。PCN表の位置 <SEQUENCE_POSITION>に述語を含める必要がある場合は'<SEQUENCE_POSITION>C'、PCN表の位置<SEQUENCE_POSITION>に述語を含める必要があり、その目的語の字句値コンポーネントも含める必要がある場合は '<SEQUENCE_POSITION>CV'

2番目のプロシージャSEM_APIS.BUILD_SPM_TABは、SVP、MVPおよびPCN表を作成して移入します。

述語情報表をSEM_APIS.BUILD_SPM_TABへの入力として指定してSVP表を作成すると、プロシージャは、MAX_CNT値が1でINCLUDE値がNULL'Y'または'V'の各述語を含むSVP表を作成します。INCLUDE値が 'N'の述語はSVP表に追加されません。

述語情報表をSEM_APIS.BUILD_SPM_TABへの入力として指定してPCN表を作成すると、INCLUDE値が'<SEQUENCE_POSITION>C'または'<SEQUENCE_POSITION>CV'の一連のプロパティのPCN表が、位置1から始まる順序で作成されます。他のINCLUDE値を持つ述語はPCN表に追加されません。

述語URISEM_APIS.BUILD_SPM_TABに指定すると、指定された述語のMVP表が作成されます。

ノート:

SVPまたはPCN表の作成時に、ネットワーク所有者に述語情報表に対する読取り権限があることを確認してください。

次の例は、SEM_APIS.GATHER_SPM_INFOおよびSEM_APIS.BUILD_SPM_TABを使用したRDFモデルのSPM表のセットの作成を示しています。これらのSPM表はSPARQL問合せの実行に自動的に使用されます。この例ではSEM_MATCHを使用しますが、Support for Apache JenaやRDFサーバーなどの他のAPIを介して実行されるSPARQL問合せでもSPM表が自動的に使用されます。

例1-94 SPM表の作成

SQL> connect rdfuser/rdfuser;
Connected.
SQL> 
SQL> -- create a schema-private network named NET1 owned by RDFUSER
SQL> exec sem_apis.create_sem_network('tbs_3',network_owner=>'RDFUSER',network_name=>'NET1');

PL/SQL procedure successfully completed.

SQL> 
SQL> -- create a semantic model
SQL> exec sem_apis.create_sem_model('M1',null,null,network_owner=>'RDFUSER',network_name=>'NET1');

PL/SQL procedure successfully completed.

SQL> 
SQL> -- add some data
SQL> begin
  2    sem_apis.update_model('M1',
  3      'PREFIX    : <http://www.example.com#>
  4       PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
  5       INSERT DATA {
  6         :john :fname "John"
  7             ; :lname "Brown"
  8             ; :height 72
  9             ; :email "john@email-example.com"
 10             ; :email "johnnyB@email-example.com"
 11             ; :nickName "Johnny B"
 12             ; :friendOf :ann
 13             ; :address [
 14                  :addrNum 20
 15                ; :addrStreet "Elm Street"
 16                ; :addrCityState [
 17                     :addrCity "Boston"
 18                   ; :addrState "MA" ] ] .
 19         :ann :fname "Ann"
 20             ; :lname "Green"
 21             ; :height 65
 22             ; :email "ann@email-example.com"
 23             ; :nickName "Annie"
 24             ; :friendOf :john
 25             ; :friendOf :bill
 26             ; :address [
 27                  :addrNum 10
 28                ; :addrStreet "Main Street"
 29                ; :addrCityState [
 30                     :addrCity "New York"
 31                   ; :addrState "NY" ] ] .
 32         :bill :fname "Bill"
 33             ; :lname "Red"
 34             ; :height 70
 35             ; :email "bill@email-example.com"
 36             ; :nickName "Billy"
 37             ; :friendOf :ann
 38             ; :friendOf :jane
 39             ; :address [
 40                  :addrNum 5
 41                ; :addrStreet "Peachtree Street"
 42                ; :addrCityState [
 43                     :addrCity "Atlanta"
 44                   ; :addrState "GA" ] ] .
 45         :jane :fname "Jane"
 46             ; :lname "Blue"
 47             ; :height 68
 48             ; :email "jane@email-example.com"
 49             ; :email "jane2@email-example.com"
 50             ; :friendOf :bill
 51             ; :address [
 52                  :addrNum 101
 53                ; :addrStreet "Maple Street"
 54                ; :addrCityState [
 55                     :addrCity "Chicago"
 56                   ; :addrState "IL" ] ] .
 57       }'
 58      ,network_owner=>'RDFUSER'
 59      ,network_name=>'NET1');
 60  end;
 61  /

PL/SQL procedure successfully completed.

SQL> 
SQL> -- gather optimizer statistics
SQL> begin
  2    sem_perf.gather_stats(
  3      network_owner=>'RDFUSER',
  4      network_name=>'NET1');
  5  end;
  6  /

PL/SQL procedure successfully completed.

SQL> 
SQL> -- create and populate a predicate information table named M1_PRED_INFO
SQL> begin
  2   sem_apis.gather_spm_info(
  3     model_name=>'M1',
  4     pred_info_tabname=>'M1_PRED_INFO',
  5     degree=>2,
  6     network_owner=>'RDFUSER',
  7     network_name=>'NET1');
  8  end;
  9  /

PL/SQL procedure successfully completed.

SQL> 
SQL> -- check M1_PRED_INFO
SQL> select * from M1_PRED_INFO;

          P_VALUE_ID PRED_NAME                                MIN_CNT MAX_CNT MED_CNT AVG_CNT TOT_CNT INCLUDE
-------------------- ---------------------------------------- ------- ------- ------- ------- ------- -------
  911778881896408883 http://www.example.com#addrCity                1       1     1.0     1.0       4
 1285894645615718351 http://www.example.com#friendOf                1       2     1.5     1.5       6
 2282073771135796724 http://www.example.com#addrCityState           1       1     1.0     1.0       4
 6664054864634376526 http://www.example.com#addrNum                 1       1     1.0     1.0       4
 7644445801044650266 http://www.example.com#lname                   1       1     1.0     1.0       4
 8337314745347241189 http://www.example.com#fname                   1       1     1.0     1.0       4
  594560333771551504 http://www.example.com#addrState               1       1     1.0     1.0       4
 2558054308995111125 http://www.example.com#nickName                1       1     1.0     1.0       3
 2930492586059823454 http://www.example.com#email                   1       2     1.5     1.5       6
 3131489775428233363 http://www.example.com#addrStreet              1       1     1.0     1.0       4
 4791477124431525340 http://www.example.com#height                  1       1     1.0     1.0       4
 5055192271510902740 http://www.example.com#address                 1       1     1.0     1.0       4

12 rows selected.

SQL> 
SQL> -- mark all properties with 'N' to initialize pred
SQL> update M1_PRED_INFO
  2  set INCLUDE = 'N';

12 rows updated.

SQL> commit;

Commit complete.

SQL> 
SQL> -- create a SVP table for single-valued predicates :fname, :lname, :height
SQL> -- mark the desired properties for inclusion
SQL> update M1_PRED_INFO
  2  set INCLUDE = 'Y'
  3  where PRED_NAME IN
  4    ('http://www.example.com#fname',
  5     'http://www.example.com#lname',
  6     'http://www.example.com#height');

3 rows updated.

SQL> commit;

Commit complete.

SQL> 
SQL> begin
  2   sem_apis.build_spm_tab(
  3     model_name=>'M1',
  4     pred_info_tabname=>'M1_PRED_INFO',
  5     pred_name=>NULL,
  6     options=>' svp_name=fnm_lnm_hght ',
  7     degree=>2,
  8     network_owner=>'RDFUSER',
  9     network_name=>'NET1');
 10  end;
 11  /

PL/SQL procedure successfully completed.

SQL> 
SQL> -- check the SVP table
SQL> select * from NET1#RDF_XT$SVP_M1__FNM_LNM_HGHT;

       START_NODE_ID G4791477124431525340 P4791477124431525340 G7644445801044650266 P7644445801044650266 G8337314745347241189 P8337314745347241189
-------------------- -------------------- -------------------- -------------------- -------------------- -------------------- --------------------
 1399946303865654932                       7949294891880010615                       5036507830384741776                       2838435233532231409
 8972322488425499169                       2028730158517518732                       6648986869806945928                       3239737248730612593
 7024748068782994892                       7603694794035016230                       8802343394415720481                       9071571320455459462
 8531245907959123227                       4318017261525689661                       9011354822640550059                         50859040499294923

4 rows selected.

SQL> 
SQL> -- create a PCN table for :address/:addrCityState/:addrState
SQL> update M1_PRED_INFO
  2  set INCLUDE = 'N';

12 rows updated.

SQL> commit;

Commit complete.

SQL> 
SQL> update M1_PRED_INFO
  2  set INCLUDE = '1C'
  3  where PRED_NAME = 'http://www.example.com#address';

1 row updated.

SQL> update M1_PRED_INFO
  2  set INCLUDE = '2C'
  3  where PRED_NAME = 'http://www.example.com#addrCityState';

1 row updated.

SQL> update M1_PRED_INFO
  2  set INCLUDE = '3C'
  3  where PRED_NAME = 'http://www.example.com#addrState';

1 row updated.

SQL> commit;

Commit complete.

SQL> 
SQL> begin
  2   sem_apis.build_spm_tab(
  3     model_name=>'M1',
  4     pred_info_tabname=>'M1_PRED_INFO',
  5     pred_name=>NULL,
  6     options=>' pcn_name=addr_state ',
  7     degree=>2,
  8     network_owner=>'RDFUSER',
  9     network_name=>'NET1');
 10  end;
 11  /

PL/SQL procedure successfully completed.

SQL> 
SQL> -- check the PCN table
SQL> select * from NET1#RDF_XT$PCN_M1__ADDR_STATE;

       START_NODE_ID G5055192271510902740 P5055192271510902740 G2282073771135796724 P2282073771135796724  G594560333771551504  P594560333771551504
-------------------- -------------------- -------------------- -------------------- -------------------- -------------------- --------------------
 8972322488425499169                       2996607272891371652                        505150577263043324                       4933462079191011078
 1399946303865654932                       2974015839258705958                        729260529101069318                       2028557412112123936
 7024748068782994892                       2903848673573351428                       3356095188852695398                       7995579594576433205
 8531245907959123227                       7284477346582444972                       5572563681970943459                       5359878998404290171

4 rows selected.

SQL> 
SQL> -- create MVP tables for :email and :friendOf
SQL> -- :email
SQL> begin
  2   sem_apis.build_spm_tab(
  3     model_name=>'M1',
  4     pred_info_tabname=>NULL,
  5     pred_name=>'<http://www.example.com#email>',
  6     degree=>2,
  7     network_owner=>'RDFUSER',
  8     network_name=>'NET1');
  9  end;
 10  /

PL/SQL procedure successfully completed.

SQL> 
SQL> -- check the MVP table
SQL> select * from NET1#RDF_XT$MVP_M1_P2930492586059823454 order by P2930492586059823454;
     
START_NODE_ID        G2930492586059823454 P2930492586059823454
-------------------- -------------------- --------------------
8531245907959123227		          1846003049324830366
7024748068782994892		          2096397932624357828
1399946303865654932		          6100245385739701229
7024748068782994892		          6480436012276020283
8972322488425499169		          7251371240613573863
8531245907959123227		          7834835188342349976


6 rows selected.

SQL> 
SQL> -- :friendOf
SQL> begin
  2   sem_apis.build_spm_tab(
  3     model_name=>'M1',
  4     pred_info_tabname=>NULL,
  5     pred_name=>'<http://www.example.com#friendOf>',
  6     degree=>2,
  7     network_owner=>'RDFUSER',
  8     network_name=>'NET1');
  9  end;
 10  /

PL/SQL procedure successfully completed.

SQL> 
SQL> -- check the MVP table
SQL> select * from NET1#RDF_XT$MVP_M1_P1285894645615718351;

       START_NODE_ID G1285894645615718351 P1285894645615718351
-------------------- -------------------- --------------------
 7024748068782994892                       1399946303865654932
 8972322488425499169                       1399946303865654932
 1399946303865654932                       7024748068782994892
 8972322488425499169                       8531245907959123227
 1399946303865654932                       8972322488425499169
 8531245907959123227                       8972322488425499169

6 rows selected.

SQL> 
SQL> -- gather optimizer statistics on SPM auxiliary tables
SQL> begin
  2    sem_perf.analyze_aux_tables(
  3      model_name=>'M1',
  4      network_owner=>'RDFUSER',
  5      network_name=>'NET1');
  6  end;
  7  /

PL/SQL procedure successfully completed.

SQL> 
SQL> -- Execute a SPARQL query that uses SPM tables
SQL> SELECT s, fname, lname, height, email, nick, friend, state
  2  FROM TABLE(SEM_MATCH(
  3  'PREFIX : <http://www.example.com#>
  4   SELECT *
  5   WHERE {
  6     ?s :fname ?fname
  7      ; :lname ?lname
  8      ; :height ?height
  9      ; :email ?email
 10      ; :nickName ?nick
 11      ; :friendOf ?friend
 12      ; :address/:addrCityState/:addrState ?state
 13   }'
 14  ,sem_models('M1')
 15  ,null,null,null,null
 16  ,' '
 17  ,null,null
 18  ,'RDFUSER','NET1'))
 19  ORDER BY 1,2,3,4,5,6,7;

S                              FNAME   LNAME   HEIGHT EMAIL                        NICK       FRIEND                         STATE
------------------------------ ------- ------- ------ ---------------------------- ---------- ------------------------------ -----
http://www.example.com#ann     Ann     Green   65     ann@email-example.com        Annie      http://www.example.com#bill    NY
http://www.example.com#ann     Ann     Green   65     ann@email-example.com        Annie      http://www.example.com#john    NY
http://www.example.com#bill    Bill    Red     70     bill@email-example.com       Billy      http://www.example.com#ann     GA
http://www.example.com#bill    Bill    Red     70     bill@email-example.com       Billy      http://www.example.com#jane    GA
http://www.example.com#john    John    Brown   72     john@email-example.com       Johnny B   http://www.example.com#ann     MA
http://www.example.com#john    John    Brown   72     johnnyB@email-example.com    Johnny B   http://www.example.com#ann     MA

6 rows selected.

SQL> 
SQL> -- Look at the SQL translation to show SPM table usage.
SQL> --
SQL> -- This SQL evaluates 9 triple patterns with only 4 joins
SQL> -- instead of the 8 joins that would normally be required
SQL> -- without SPM tables.
SQL> --
SQL> -- The SVP table is used for :fname, :lname, :height.
SQL> -- MVP tables are used for :email and :friendOf.
SQL> -- RDF_LINK$ isused for :nickName.
SQL> -- The PCN table is used for the sequence
SQL> -- :address/:addrCityState/:addrState
SQL> SELECT SEM_APIS.SPARQL_TO_SQL(
  2  'PREFIX : <http://www.example.com#>
  3   SELECT *
  4   WHERE {
  5     ?s :fname ?fname
  6      ; :lname ?lname
  7      ; :height ?height
  8      ; :email ?email
  9      ; :nickName ?nick
 10      ; :friendOf ?friend
 11      ; :address/:addrCityState/:addrState ?state
 12   }'
 13  ,sem_models('M1')
 14  ,null,null,null
 15  ,' '
 16  ,null,null
 17  ,'RDFUSER','NET1') AS SQL_TRANS
 18  FROM SYS.DUAL;

SQL_TRANS
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SELECT * FROM (
SELECT /*+ NO_MERGE(R) NO_SWAP_JOIN_INPUTS(R) LEADING(R V0 V1 V2 V3 V4 V5 V6 V7) NO_SWAP_JOIN_INPUTS(V0) NO_SWAP_JOIN_INPUTS(V1) NO_SWAP_JOIN_INPUTS(V2) NO_SWAP_JOIN_INPUTS(V3) NO_SWAP_JOIN_INPUTS(V4) NO_SWAP_JOIN_INPUTS(V5) NO_SWAP_JOIN_INPUTS(V6) NO_SWAP_JOIN_INPUTS(V7) */ V0.VNAME_PREFIX || V0.VNAME_SUFFIX AS S, 
V0.VALUE_ID AS S$RDFVID, V0.VNAME_PREFIX AS S$_PREFIX, V0.VNAME_SUFFIX AS S$_SUFFIX,  (CASE WHEN V0.VALUE_TYPE IS NULL THEN NULL WHEN V0.VALUE_TYPE IN ('UR','URI') THEN 'URI'
 WHEN V0.VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
 ELSE 'LIT'
END)  AS S$RDFVTYP, V0.LONG_VALUE AS S$RDFCLOB, V0.LITERAL_TYPE AS S$RDFLTYP, V0.LANGUAGE_TYPE AS S$RDFLANG,
… OMITTED …
1 AS SEM$ROWNUM
FROM (SELECT SVP0.START_NODE_ID AS S$RDFVID,
SVP0.P7644445801044650266 AS LNAME$RDFVID,
MVP1.P1285894645615718351 AS FRIEND$RDFVID,
T4.CANON_END_NODE_ID AS NICK$RDFVID,
PCN0.P594560333771551504 AS STATE$RDFVID,
SVP0.P4791477124431525340 AS HEIGHT$RDFVID,
MVP0.P2930492586059823454 AS EMAIL$RDFVID,
SVP0.P8337314745347241189 AS FNAME$RDFVID,
SVP0.START_NODE_ID AS BGP$1
FROM (
SELECT * FROM "RDFUSER".NET1#RDFM_M1) T4,
"RDFUSER".NET1#RDF_XT$SVP_M1__FNM_LNM_HGHT SVP0,
"RDFUSER".NET1#RDF_XT$PCN_M1__ADDR_STATE PCN0,
"RDFUSER".NET1#RDF_XT$MVP_M1_P2930492586059823454 MVP0,
"RDFUSER".NET1#RDF_XT$MVP_M1_P1285894645615718351 MVP1
WHERE SVP0.P8337314745347241189 IS NOT NULL AND
SVP0.P7644445801044650266 IS NOT NULL AND
SVP0.P4791477124431525340 IS NOT NULL AND
T4.P_VALUE_ID = 2558054308995111125 AND
SVP0.START_NODE_ID = MVP0.START_NODE_ID AND
SVP0.START_NODE_ID = T4.START_NODE_ID AND
SVP0.START_NODE_ID = MVP1.START_NODE_ID AND
SVP0.START_NODE_ID = PCN0.START_NODE_ID
) R, 
"RDFUSER".NET1#RDF_VALUE$ V0, "RDFUSER".NET1#RDF_VALUE$ V1, "RDFUSER".NET1#RDF_VALUE$ V2, "RDFUSER".NET1#RDF_VALUE$ V3, "RDFUSER".NET1#RDF_VALUE$ V4, "RDFUSER".NET1#RDF_VALUE$ V5, "RDFUSER".NET1#RDF_VALUE$ V6, "RDFUSER".NET1#RDF_VALUE$ V7
WHERE (1=1)  AND (R.S$RDFVID = V0.VALUE_ID) AND (R.LNAME$RDFVID = V1.VALUE_ID) AND (R.FRIEND$RDFVID = V2.VALUE_ID) AND (R.NICK$RDFVID = V3.VALUE_ID) AND (R.STATE$RDFVID = V4.VALUE_ID) AND (R.HEIGHT$RDFVID = V5.VALUE_ID) AND (R.EMAIL$RDFVID = V6.VALUE_ID) AND (R.FNAME$RDFVID = V7.VALUE_ID)
) WHERE (1=1)


1 row selected.
1.6.13.5 SPM補助表への字句値の組込み

SPM補助表には、デフォルトでオブジェクト値の値IDが含まれます。SPM表のオブジェクトに字句の値を含めることもできます。字句の値を含めると、問合せの実行を高速化するために、追加の記憶域要件を犠牲にして、RDF_VALUE$表との結合が除外される可能性があります。

プロパティに字句値を含めることを選択した場合、字句プロパティ値の新しい列がSVP、PCN表に追加されます。これらの列は、RDF_VALUE$の同じ名前を持つ列に正確に対応していることに注意してください。次の表では、字句プロパティ値を含めるために追加される列について説明します。

表1-22 MVN、PCNおよびSVP表の字句値列

列名 タイプ 説明
<PREDICATE_ID>_VALUE_TYPE VARCHAR2(10) VALUE_NAME列に格納されたテキスト情報のタイプ。可能な値は次のとおりです。
  • UR - URI
  • BN - 空白ノード
  • PL - プレーン・リテラル
  • PL@ - 言語タグを持つプレーン・リテラル
  • PLL - プレーン・ロング・リテラル
  • PLL@ - 言語タグ付きのプレーン・ロング・リテラル
  • TL - 型付きリテラル
  • TLL - 型付きロング・リテラル

    ロング・リテラルは、4000バイトを超えるリテラルです。

<PREDICATE_ID>_VNAME_PREFIX VARCHAR2(4000)

字句の値の長さが4000バイト以下の場合、この列に字句の値の一部である接頭辞が格納されます。接頭辞の計算には、 SEM_APIS.VALUE_NAME_PREFIXプロシージャを使用できます。

たとえば、山カッコを除く字句<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>の一部に対応する接頭辞は、http://www.w3.org/1999/02/22-rdf-syntax-ns#です。

<PREDICATE_ID>_VNAME_SUFFIX VARCHAR2(512)

字句の値の長さが4000バイト以下の場合、この列に字句の値の一部である接尾辞が格納されます。接尾辞の計算には、SEM_APIS.VALUE_NAME_SUFFIXファンクションを使用できます。VNAME_PREFIX列の説明に記載されている字句の値の場合、接尾辞はtypeです

<PREDICATE_ID>_LITERAL_TYPE VARCHAR2(1000)

型付きリテラルの場合は型情報、それ以外の場合はNULL。たとえば、1999-08-16という作成日を示す行の場合、VALUE_TYPE列にはTLが格納され、 LITERAL_TYPE 列にはhttp://www.w3.org/2001/XMLSchema#dateが格納されます。

<PREDICATE_ID>_LANGUAGE_TYPE VARCHAR2(80)

言語タグ付きのリテラル(つまり、VALUE_TYPEPL@またはPLL@の場合)の言語タグ(フランス語の場合のfrなど)。それ以外の場合、この列はNULL値です。

<PREDICATE_ID>_ORDER_NUM NUMBER

数の型に対するオーダーを表します。ORDER BY問合せのパフォーマンスを向上させるために使用します。

<PREDICATE_ID>_ORDER_DATE TIMESTAMP(6)WITH TIME ZONE

日付の型に基づいたオーダーを表します。ORDER BY問合せのパフォーマンスを向上させるために使用します。

<PREDICATE_ID>_LONG_VALUE VARCHAR2(30)

字句の値の長さが4000バイトを超える場合の文字列。それ以外の場合、この列はNULL値です。

.

SPM補助表の作成時に字句の値を含めるには、いくつかの方法があります。字句の値の追加は、述語ごとに制御できます。字句の値を含める様々な方法を次に示します。

  • SVP、MVPまたはPCN表を構築または再構築する場合:
    • 字句の値を含める述語情報表の述語ごとに、INCLUDEの値を'V'または'<SEQUENCE_POSITION>CV'に設定します。
    • オプション引数に文字列'INCLUDE_VALUE=T'を追加してSEM_APIS.BUILD_SPM_TABを実行します。

    ノート:

    前述の2つのオプションは、SVP、MVPまたはPCN表を構築または再構築する際に、多数のインライン字句値を追加する最も効率的な方法です。
  • 既存のSVP、PCNまたはMVP表を変更する場合:
    • 'ADD_VALUE'に等しいコマンドおよび字句の値を含める述語と同じpred_nameを使用して、SEM_APIS.ALTER_SPM_TABを実行します。

次の例は、例1-94から継続しています。:fname, :height, :email and :addrStateの字句の値を追加する方法を示しています。

例1-95 SPM補助表への字句値の組込み

SQL> -- Rebuild the SVP table so that it includes lexical values for
SQL> -- :fname and :height
SQL> -- Set INCLUDE='Y' for :lname
SQL> -- Set INCLUDE='V' for :fname and :height
SQL> create or replace view M1_pred_info_view as
  2 select p_value_id, pred_name, max_cnt
  3 , (case pred_name
  4 when 'http://www.example.com#fname' then 'V'
  5 when 'http://www.example.com#lname' then 'Y'
  6 when 'http://www.example.com#height' then 'V'
  7 else 'N'
  8 end) include
  9 from M1_pred_info
 10 ;

View created.

SQL> 
SQL> -- Rebuild the SVP table. Note the use of CREATE_ANYWAY=T for rebuild.
SQL> -- Note that a rebuild is the most efficient way to add a large number
SQL> -- of in-line lexical values.
SQL> begin
  2   sem_apis.build_spm_tab(
  3     model_name=>'M1',
  4     pred_info_tabname=>'M1_PRED_INFO_VIEW',
  5     pred_name=>NULL,
  6     degree=>2,
  7     options=>' svp_name=fnm_lnm_hght CREATE_ANYWAY=T ',
  8     network_owner=>'RDFUSER',
  9     network_name=>'NET1');
 10  end;
 11  /

PL/SQL procedure successfully completed.

SQL> 
SQL> -- Check columns in the SVP table
SQL> desc NET1#RDF_XT$SVP_M1__FNM_LNM_HGHT;
Name                               Null?    Type                        
---------------------------------- -------- --------------------------- 
START_NODE_ID                      NOT NULL NUMBER                      
G4791477124431525340                        NUMBER                      
P4791477124431525340                        NUMBER                      
G8337314745347241189                        NUMBER                      
P8337314745347241189                        NUMBER                      
G7644445801044650266                        NUMBER                      
P7644445801044650266                        NUMBER                      
P4791477124431525340_VALUE_TYPE             VARCHAR2(10)                
P4791477124431525340_VNAME_PREFIX           VARCHAR2(4000)              
P4791477124431525340_VNAME_SUFFIX           VARCHAR2(512)               
P4791477124431525340_LITERAL_TYPE           VARCHAR2(1000)              
P4791477124431525340_LANGUAGE_TYPE          VARCHAR2(80)                
P4791477124431525340_ORDER_NUM              NUMBER                      
P4791477124431525340_ORDER_DATE             TIMESTAMP(6) WITH TIME ZONE 
P4791477124431525340_LONG_VALUE             CLOB                        
P8337314745347241189_VALUE_TYPE             VARCHAR2(10)                
P8337314745347241189_VNAME_PREFIX           VARCHAR2(4000)              
P8337314745347241189_VNAME_SUFFIX           VARCHAR2(512)               
P8337314745347241189_LITERAL_TYPE           VARCHAR2(1000)              
P8337314745347241189_LANGUAGE_TYPE          VARCHAR2(80)                
P8337314745347241189_ORDER_NUM              NUMBER                      
P8337314745347241189_ORDER_DATE             TIMESTAMP(6) WITH TIME ZONE 
P8337314745347241189_LONG_VALUE             CLOB                                                                                                                                                                         CLOB

SQL> 
SQL> -- create a PCN table for :address/:addrCityState/:addrState
SQL> -- Add in-line lexical value for :addrState
SQL> -- Add trailing V to indicate value inclusion
SQL> create or replace view M1_pred_info_view as
  2 select p_value_id, pred_name, max_cnt,
  3 (case pred_name
  4 when 'http://www.example.com#address' then '1C'
  5 when 'http://www.example.com#addrCityState' then '2C'
  6 when 'http://www.example.com#addrState' then '3CV'
  7 else 'N'
  8 end) include
  9 from M1_pred_info
 10 ;

View created.
SQL> 
SQL> begin
  2   sem_apis.build_spm_tab(
  3     model_name=>'M1',
  4     pred_info_tabname=>'M1_PRED_INFO_VIEW',
  5     pred_name=>NULL,
  6     options=>' pcn_name=addr_state CREATE_ANYWAY=T ',
  7     degree=>2,
  8     network_owner=>'RDFUSER',
  9     network_name=>'NET1');
 10  end;
 11  /

PL/SQL procedure successfully completed.

SQL> 
SQL> -- check the PCN table columns
SQL> desc NET1#RDF_XT$PCN_M1__ADDR_STATE;
Name                              Null?    Type                        
--------------------------------- -------- --------------------------- 
START_NODE_ID                     NOT NULL NUMBER                      
G5055192271510902740                       NUMBER                      
P5055192271510902740                       NUMBER                      
G2282073771135796724                       NUMBER                      
P2282073771135796724                       NUMBER                      
G594560333771551504                        NUMBER                      
P594560333771551504                        NUMBER                      
P594560333771551504_VALUE_TYPE             VARCHAR2(10)                
P594560333771551504_VNAME_PREFIX           VARCHAR2(4000)              
P594560333771551504_VNAME_SUFFIX           VARCHAR2(512)               
P594560333771551504_LITERAL_TYPE           VARCHAR2(1000)              
P594560333771551504_LANGUAGE_TYPE          VARCHAR2(80)                
P594560333771551504_ORDER_NUM              NUMBER                      
P594560333771551504_ORDER_DATE             TIMESTAMP(6) WITH TIME ZONE 
P594560333771551504_LONG_VALUE             CLOB                                                                                                                                                                                        CLOB

SQL> 
SQL> -- Add in-line lexical value for email
SQL> begin
  2    sem_apis.alter_spm_tab(
  3      model_name=>'m1',
  4      pred_name=>'<http://www.example.com#email>',
  5      command=>'ADD_VALUE',
  6      network_owner=>'RDFUSER',
  7      network_name=>'NET1');
  8  end;
  9  /

PL/SQL procedure successfully completed.

SQL> 
SQL> -- Check columns in the MVP table for email
SQL> desc NET1#RDF_XT$MVP_M1_P2930492586059823454;
Name                               Null?    Type                        
---------------------------------- -------- --------------------------- 
START_NODE_ID                      NOT NULL NUMBER                      
G2930492586059823454                        NUMBER                      
P2930492586059823454                        NUMBER                      
P2930492586059823454_VALUE_TYPE             VARCHAR2(10)                
P2930492586059823454_VNAME_PREFIX           VARCHAR2(4000)              
P2930492586059823454_VNAME_SUFFIX           VARCHAR2(512)               
P2930492586059823454_LITERAL_TYPE           VARCHAR2(1000)              
P2930492586059823454_LANGUAGE_TYPE          VARCHAR2(80)                
P2930492586059823454_ORDER_NUM              NUMBER                      
P2930492586059823454_ORDER_DATE             TIMESTAMP(6) WITH TIME ZONE 
P2930492586059823454_LONG_VALUE             CLOB  

SQL> 
SQL> -- Gather statistics since the tables have changed
SQL> begin
  2    sem_perf.analyze_aux_tables(
  3      model_name=>'M1',
  4      network_owner=>'RDFUSER',
  5      network_name=>'NET1');
  6  end;
  7  /

PL/SQL procedure successfully completed.

SQL> 
SQL> -- Run a SPARQL query using the new auxiliary tables
SQL> SELECT s, fname, lname, height, email, nick, friend, state
  2  FROM TABLE(SEM_MATCH(
  3  'PREFIX : <http://www.example.com#>
  4   SELECT *
  5   WHERE {
  6     ?s :fname ?fname
  7      ; :lname ?lname
  8      ; :height ?height
  9      ; :email ?email
 10      ; :nickName ?nick
 11      ; :friendOf ?friend
 12      ; :address/:addrCityState/:addrState ?state .
 13   }'
 14  ,sem_models('M1')
 15  ,null,null,null,null
 16  ,' '
 17  ,null,null
 18  ,'RDFUSER','NET1'))
 19  ORDER BY 1,2,3,4,5,6,7;

S                              FNAME   LNAME   HEIGHT EMAIL                       NICK       FRIEND                         STATE
------------------------------ ------- ------- ------ --------------------------- ---------- ------------------------------ -----
http://www.example.com#ann     Ann     Green   65     ann@email-example.com        Annie      http://www.example.com#bill    NY
http://www.example.com#ann     Ann     Green   65     ann@email-example.com        Annie      http://www.example.com#john    NY
http://www.example.com#bill    Bill    Red     70     bill@email-example.com       Billy      http://www.example.com#ann     GA
http://www.example.com#bill    Bill    Red     70     bill@email-example.com       Billy      http://www.example.com#jane    GA
http://www.example.com#john    John    Brown   72     john@email-example.com       Johnny B   http://www.example.com#ann     MA
http://www.example.com#john    John    Brown   72     johnnyB@email-example.com    Johnny B   http://www.example.com#ann     MA

6 rows selected.

SQL> 
SQL> -- Look at the SQL translation to show in-line lexical
SQL> -- value usage.
SQL> --
SQL> -- This SQL has eliminated 4 RDF_VALUE$ joins compared
SQL> -- to the previous query execution.
SQL> SELECT SEM_APIS.SPARQL_TO_SQL(
  2  'PREFIX : <http://www.example.com#>
  3   SELECT *
  4   WHERE {
  5     ?s :fname ?fname
  6      ; :lname ?lname
  7      ; :height ?height
  8      ; :email ?email
  9      ; :nickName ?nick
 10      ; :friendOf ?friend
 11      ; :address/:addrCityState/:addrState ?state .
 12   }'
 13  ,sem_models('M1')
 14  ,null,null,null
 15  ,' '
 16  ,null,null
 17  ,'RDFUSER','NET1') AS SQL_TRANS
 18  FROM SYS.DUAL;

SQL_TRANS
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SELECT * FROM (
SELECT /*+ NO_MERGE(R) NO_SWAP_JOIN_INPUTS(R) LEADING(R V0 V1 V2 V3) NO_SWAP_JOIN_INPUTS(V0) NO_SWAP_JOIN_INPUTS(V1) NO_SWAP_JOIN_INPUTS(V2) NO_SWAP_JOIN_INPUTS(V3) */ V0.VNAME_PREFIX || V0.VNAME_SUFFIX AS S, V0.VALUE_ID AS S$RDFVID, V0.VNAME_PREFIX AS S$_PREFIX, V0.VNAME_SUFFIX AS S$_SUFFIX,  (CASE WHEN V0.VALUE_TYPE
IS NULL THEN NULL WHEN V0.VALUE_TYPE IN ('UR','URI') THEN 'URI'
 WHEN V0.VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
 ELSE 'LIT'
END)  AS S$RDFVTYP, V0.LONG_VALUE AS S$RDFCLOB, V0.LITERAL_TYPE AS S$RDFLTYP, V0.LANGUAGE_TYPE AS S$RDFLANG,
… OMITTED …
1 AS SEM$ROWNUM
FROM (SELECT SVP0.START_NODE_ID AS S$RDFVID,
SVP0.P7644445801044650266 AS LNAME$RDFVID,
MVP1.P1285894645615718351 AS FRIEND$RDFVID,
T4.CANON_END_NODE_ID AS NICK$RDFVID,
PCN0.P594560333771551504_VNAME_PREFIX || PCN0.P594560333771551504_VNAME_SUFFIX AS STATE,  (CASE WHEN PCN0.P594560333771551504_VALUE_TYPE IS NULL THEN NULL WHEN PCN0.P594560333771551504_VALUE_TYPE IN ('UR','URI') THEN 'URI'
 WHEN PCN0.P594560333771551504_VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
 ELSE 'LIT'
END)  AS STATE$RDFVTYP, PCN0.P594560333771551504 AS STATE$RDFVID, PCN0.P594560333771551504_VNAME_PREFIX AS STATE$_PREFIX, PCN0.P594560333771551504_VNAME_SUFFIX AS STATE$_SUFFIX, PCN0.P594560333771551504_LITERAL_TYPE AS STATE$RDFLTYP, PCN0.P594560333771551504_LANGUAGE_TYPE AS STATE$RDFLANG, PCN0.P594560333771551504_LONG
_VALUE AS STATE$RDFCLOB,
SVP0.P4791477124431525340_VNAME_PREFIX || SVP0.P4791477124431525340_VNAME_SUFFIX AS HEIGHT,  (CASE WHEN SVP0.P4791477124431525340_VALUE_TYPE IS NULL THEN NULL WHEN SVP0.P4791477124431525340_VALUE_TYPE IN ('UR','URI') THEN 'URI'
 WHEN SVP0.P4791477124431525340_VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
 ELSE 'LIT'
END)  AS HEIGHT$RDFVTYP, SVP0.P4791477124431525340 AS HEIGHT$RDFVID, SVP0.P4791477124431525340_VNAME_PREFIX AS HEIGHT$_PREFIX, SVP0.P4791477124431525340_VNAME_SUFFIX AS HEIGHT$_SUFFIX, SVP0.P4791477124431525340_LITERAL_TYPE AS HEIGHT$RDFLTYP, SVP0.P4791477124431525340_LANGUAGE_TYPE AS HEIGHT$RDFLANG, SVP0.P479147712443
1525340_LONG_VALUE AS HEIGHT$RDFCLOB,
MVP0.P2930492586059823454_VNAME_PREFIX || MVP0.P2930492586059823454_VNAME_SUFFIX AS EMAIL,  (CASE WHEN MVP0.P2930492586059823454_VALUE_TYPE IS NULL THEN NULL WHEN MVP0.P2930492586059823454_VALUE_TYPE IN ('UR','URI') THEN 'URI'
 WHEN MVP0.P2930492586059823454_VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
 ELSE 'LIT'
END)  AS EMAIL$RDFVTYP, MVP0.P2930492586059823454 AS EMAIL$RDFVID, MVP0.P2930492586059823454_VNAME_PREFIX AS EMAIL$_PREFIX, MVP0.P2930492586059823454_VNAME_SUFFIX AS EMAIL$_SUFFIX, MVP0.P2930492586059823454_LITERAL_TYPE AS EMAIL$RDFLTYP, MVP0.P2930492586059823454_LANGUAGE_TYPE AS EMAIL$RDFLANG, MVP0.P293049258605982345
4_LONG_VALUE AS EMAIL$RDFCLOB,
SVP0.P8337314745347241189_VNAME_PREFIX || SVP0.P8337314745347241189_VNAME_SUFFIX AS FNAME,  (CASE WHEN SVP0.P8337314745347241189_VALUE_TYPE IS NULL THEN NULL WHEN SVP0.P8337314745347241189_VALUE_TYPE IN ('UR','URI') THEN 'URI'
 WHEN SVP0.P8337314745347241189_VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
 ELSE 'LIT'
END)  AS FNAME$RDFVTYP, SVP0.P8337314745347241189 AS FNAME$RDFVID, SVP0.P8337314745347241189_VNAME_PREFIX AS FNAME$_PREFIX, SVP0.P8337314745347241189_VNAME_SUFFIX AS FNAME$_SUFFIX, SVP0.P8337314745347241189_LITERAL_TYPE AS FNAME$RDFLTYP, SVP0.P8337314745347241189_LANGUAGE_TYPE AS FNAME$RDFLANG, SVP0.P833731474534724118
9_LONG_VALUE AS FNAME$RDFCLOB,
SVP0.START_NODE_ID AS BGP$1
FROM (
SELECT * FROM "RDFUSER".NET1#RDFM_M1) T4,
"RDFUSER".NET1#RDF_XT$SVP_M1__FNM_LNM_HGHT SVP0,
"RDFUSER".NET1#RDF_XT$PCN_M1__ADDR_STATE PCN0,
"RDFUSER".NET1#RDF_XT$MVP_M1_P2930492586059823454 MVP0,
"RDFUSER".NET1#RDF_XT$MVP_M1_P1285894645615718351 MVP1
WHERE 
SVP0.P8337314745347241189 IS NOT NULL AND
SVP0.P7644445801044650266 IS NOT NULL AND
SVP0.P4791477124431525340 IS NOT NULL AND
T4.P_VALUE_ID = 2558054308995111125 AND
SVP0.START_NODE_ID = MVP0.START_NODE_ID AND
SVP0.START_NODE_ID = T4.START_NODE_ID AND
SVP0.START_NODE_ID = MVP1.START_NODE_ID AND
SVP0.START_NODE_ID = PCN0.START_NODE_ID
) R, 
"RDFUSER".NET1#RDF_VALUE$ V0, "RDFUSER".NET1#RDF_VALUE$ V1, "RDFUSER".NET1#RDF_VALUE$ V2, "RDFUSER".NET1#RDF_VALUE$ V3
WHERE (1=1)  AND (R.S$RDFVID = V0.VALUE_ID) AND (R.LNAME$RDFVID = V1.VALUE_ID) AND (R.FRIEND$RDFVID = V2.VALUE_ID) AND (R.NICK$RDFVID = V3.VALUE_ID)
) WHERE (1=1)


1 row selected.

SQL> 
SQL> -- In addition to value projection. In-line lexical values
SQL> -- can be used to evaluate FILTER conditions.
SQL> -- The value for ?height can be taken directly from the
SQL> -- SVP table in this case.
SQL> SELECT s, height
  2  FROM TABLE(SEM_MATCH(
  3  'PREFIX : <http://www.example.com#>
  4   SELECT ?s ?height
  5   WHERE {
  6     ?s :fname ?fname
  7      ; :lname ?lname
  8      ; :height ?height
  9     FILTER (?height >= 72)
 10   }'
 11  ,sem_models('M1')
 12  ,null,null,null,null
 13  ,' '
 14  ,null,null
 15  ,'RDFUSER','NET1'))
 16  ORDER BY 1,2;

S                              HEIGHT
------------------------------ ------
http://www.example.com#john    72

1 row selected.

SQL> 
SQL> -- Look at the SQL translation to show in-line lexical
SQL> -- value usage for ?height >= 72.
SQL> SELECT SEM_APIS.SPARQL_TO_SQL(
  2  'PREFIX : <http://www.example.com#>
  3   SELECT ?s ?height
  4   WHERE {
  5     ?s :fname ?fname
  6      ; :lname ?lname
  7      ; :height ?height
  8     FILTER (?height >= 72)
  9   }'
 10  ,sem_models('M1')
 11  ,null,null,null
 12  ,' '
 13  ,null,null
 14  ,'RDFUSER','NET1') AS SQL_TRANS
 15  FROM SYS.DUAL;

SQL_TRANS
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SELECT * FROM (
SELECT /*+ NO_MERGE(R) NO_SWAP_JOIN_INPUTS(R) LEADING(R V0) NO_SWAP_JOIN_INPUTS(V0) */ V0.VNAME_PREFIX || V0.VNAME_SUFFIX AS S, V0.VALUE_ID AS S$RDFVID, V0.VNAME_PREFIX AS S$_PREFIX, V0.VNAME_SUFFIX AS S$_SUFFIX,  (CASE WHEN V0.VALUE_TYPE IS NULL THEN NULL WHEN V0.VALUE_TYPE IN ('UR','URI') THEN 'URI'
 WHEN V0.VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
 ELSE 'LIT'
END)  AS S$RDFVTYP, V0.LONG_VALUE AS S$RDFCLOB, V0.LITERAL_TYPE AS S$RDFLTYP, V0.LANGUAGE_TYPE AS S$RDFLANG,
R.HEIGHT, R.HEIGHT$RDFVID, R.HEIGHT$_PREFIX, R.HEIGHT$_SUFFIX, R.HEIGHT$RDFVTYP, R.HEIGHT$RDFCLOB, R.HEIGHT$RDFLTYP, R.HEIGHT$RDFLANG,
1 AS SEM$ROWNUM
FROM (SELECT SVP0.START_NODE_ID AS S$RDFVID,
SVP0.P7644445801044650266 AS LNAME$RDFVID,
SVP0.P4791477124431525340_VNAME_PREFIX || SVP0.P4791477124431525340_VNAME_SUFFIX AS HEIGHT,  (CASE WHEN SVP0.P4791477124431525340_VALUE_TYPE IS NULL THEN NULL WHEN SVP0.P4791477124431525340_VALUE_TYPE IN ('UR','URI') THEN 'URI'
 WHEN SVP0.P4791477124431525340_VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
 ELSE 'LIT'
END)  AS HEIGHT$RDFVTYP, SVP0.P4791477124431525340 AS HEIGHT$RDFVID, SVP0.P4791477124431525340_VNAME_PREFIX AS HEIGHT$_PREFIX, SVP0.P4791477124431525340_VNAME_SUFFIX AS HEIGHT$_SUFFIX, SVP0.P4791477124431525340_LITERAL_TYPE AS HEIGHT$RDFLTYP, SVP0.P4791477124431525340_LANGUAGE_TYPE AS HEIGHT$RDFLANG, SVP0.P479147712443
1525340_LONG_VALUE AS HEIGHT$RDFCLOB,
SVP0.P8337314745347241189 AS FNAME$RDFVID,
SVP0.START_NODE_ID AS BGP$1
FROM "RDFUSER".NET1#RDF_XT$SVP_M1__FNM_LNM_HGHT SVP0
WHERE
SVP0.P8337314745347241189 IS NOT NULL AND
SVP0.P7644445801044650266 IS NOT NULL AND
SVP0.P4791477124431525340 IS NOT NULL AND
(SVP0.P4791477124431525340_ORDER_NUM >= to_number(72))
) R, 
"RDFUSER".NET1#RDF_VALUE$ V0
WHERE (1=1)  AND (R.S$RDFVID = V0.VALUE_ID)
) WHERE (1=1)


1 row selected.
1.6.13.6 SPM補助表でのセカンダリ索引の作成

特定のSPARQLワークロードでは、通常、一部の述語はグループとしてまとめてアクセスされます。SVP表のセカンダリ索引を使用すると、このようなワークロードを高速化できます。

SEM_APIS.CREATE_INDEX_ON_SPM_TABプロシージャは、RDFモデルのSVP、MVPおよびPCN表に索引を作成します。

表1-23 SEM_APIS.CREATE_INDEX_ON_SPM_TAB プロシージャのパラメータ

引数 タイプ デフォルト 説明
INDEX_NAME VARCHAR2   作成する索引の名前。
MODEL_NAME VARCHAR2   ターゲット補助表のデータのソースであるRDFモデル。
KEY_STRING VARCHAR2  

索引キーは空白で区切られた値で、次の特徴があります。

  • start_node_idの位置を示すために、最大で1つの'S'を使用します(指定した場合、一意の索引が作成されます)。
  • 述語のリストに対応するすべてのG_IDのパラレル・リストの位置を示すために、最大で1つのG*を使用できます(G*とG+または+Gは混在できません)。
  • 複数の'G+'または'+G'記号を使用して、リスト内の述語に対応するG_IDの選択的な包含(直前または直後の述語に関連付け)を示します(ノート: 述語の出現前の+Gおよび述語のすべての出現後のG+は無効です)。
  • 索引に対して選択された値列: VP、VS、VT、LT、LA、VN、VD。Gの場合と同様に、接頭辞または接尾辞として「+」を使用して、P<pid>列との関連付けを示すことができます。接尾辞「*」は使用できません。(VP: vname_prefix、VS: vname_suffix、VT: 値タイプ、LT: リテラル・タイプ、LA: 言語タイプ、VN: オーダー番号、VD: オーダー日)。
PRED_NAME VARCHAR2 NULL NULL以外の値は、索引を作成するMVP表を識別します。
TABLESPACE_NAME DBMS_ID NULL  
DEGREE NUMBER NULL 並列度。
PREFIXES VARCHAR2 NULL SPARQLプリアンブル・スタイル文字列は次の例に示すとおりです。
  • PREFIX ex: <http://www.example.org/>
  • PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
  • PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX_LENGTH NUMBER NULL 圧縮される列数。
OPTIONS VARCHAR2 NULL
  • PCN_NAME=: 指定されたPCN表に索引が作成されます。
  • SVP_NAME=: 指定されたSVP表に索引が作成されます。
  • CREATE_ANYWAY=T: 索引は置換されます。
NETWORK_OWNER DBMS_ID NULL ネットワーク所有者の名前。
NETWORK_NAME VARCHAR2 NULL ネットワーク名です。

例1-96 SPM補助表の索引を検査するビューの作成

次の例では、現在のユーザーが所有するMYNETネットワーク内のすべてのSPM表の索引を検査するビューを作成します。

CREATE VIEW spm_index_info AS
SELECT x.index_name, x.table_name, x.uniqueness, x.compression, x.prefix_length, x.tablespace_name
     , listagg(xc.column_name,',') WITHIN GROUP (ORDER BY xc.column_position) key
  FROM sys.user_indexes x, sys.user_ind_columns xc
 WHERE x.table_name like 'MYNET#RDF_XT$%' and x.index_name = xc.index_name
GROUP BY x.table_name, x.index_name, x.uniqueness, x.compression, x.prefix_length, x.tablespace_name;

例1-97 SPM補助表でのセカンダリ索引の作成

次の例は、SPM補助表での2次索引の作成を示しています。

SQL> -- create index
SQL> -- SVP
SQL> exec sem_apis.create_index_on_spm_tab('idx1', 'm1',  'ex:works_for +G G+ ex:friend_of S',  prefixes=>' PREFIX : <http://wwww.nothing.org/> PREFIX ex: <http://www.example.org/>', prefix_length=> 4, network_owner=>'rdfuser', network_name=>'mynet');

PL/SQL procedure successfully completed.

SQL> 
SQL> select * from spm_index_info order by 1,2;

INDEX_NAME                               TABLE_NAME                               UNIQUENES COMPRESSION   PREFIX_LENGTH TABLESPACE_NAME
---------------------------------------- ---------------------------------------- --------- ------------- ------------- ------------------------------
KEY
------------------------------------------------------------------------------------------------------------------------------------------------------
IDX1                                     MYNET#RDF_XT$SVP_M1                      UNIQUE    ENABLED                   4 TBS_3
P805152655817489328,G805152655817489328,G2302183899373633243,P2302183899373633243,START_NODE_ID

MYNET#RDF_XX$MVP_M1_P4326314471650369210 MYNET#RDF_XT$MVP_M1_P4326314471650369210 NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1_UQ__DRIVES           MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1_UQ__LINKED           MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1__DRIVES_P14284748913 MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
81274755
P1428474891381274755
MYNET#RDF_XX$PCN_M1__DRIVES_P43263144716 MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
50369210
P4326314471650369210
MYNET#RDF_XX$PCN_M1__LINKED_P12357259844 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
93469672
P1235725984493469672
MYNET#RDF_XX$PCN_M1__LINKED_P23021838993 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
73633243
P2302183899373633243
MYNET#RDF_XX$PCN_M1__LINKED_P80515265581 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
7489328
P805152655817489328

MYNET#RDF_XX$SVP_M1_UQ                   MYNET#RDF_XT$SVP_M1                      UNIQUE    DISABLED                    TBS_3
START_NODE_ID
10 rows selected.



SQL> drop index idx1;

Index dropped.

SQL> 
SQL> -- SVP no prefixes
SQL> exec sem_apis.create_index_on_spm_tab('idx1', 'm1',  '<http://www.example.org/works_for> +G G+ <http://www.example.org/friend_of> S', network_owner=>'rdfuser', network_name=>'mynet');

PL/SQL procedure successfully completed.

SQL> 
SQL> select * from spm_index_info order by 1,2;

INDEX_NAME                               TABLE_NAME                               UNIQUENES COMPRESSION   PREFIX_LENGTH TABLESPACE_NAME
---------------------------------------- ---------------------------------------- --------- ------------- ------------- ------------------------------
KEY
------------------------------------------------------------------------------------------------------------------------------------------------------
IDX1                                     MYNET#RDF_XT$SVP_M1                      UNIQUE    DISABLED                    TBS_3
P805152655817489328,G805152655817489328,G2302183899373633243,P2302183899373633243,START_NODE_ID

MYNET#RDF_XX$MVP_M1_P4326314471650369210 MYNET#RDF_XT$MVP_M1_P4326314471650369210 NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1_UQ__DRIVES           MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1_UQ__LINKED           MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1__DRIVES_P14284748913 MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
81274755
P1428474891381274755
MYNET#RDF_XX$PCN_M1__DRIVES_P43263144716 MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
50369210
P4326314471650369210
MYNET#RDF_XX$PCN_M1__LINKED_P12357259844 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
93469672
P1235725984493469672
MYNET#RDF_XX$PCN_M1__LINKED_P23021838993 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
73633243
P2302183899373633243
MYNET#RDF_XX$PCN_M1__LINKED_P80515265581 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
7489328
P805152655817489328

MYNET#RDF_XX$SVP_M1_UQ                   MYNET#RDF_XT$SVP_M1                      UNIQUE    DISABLED                    TBS_3
START_NODE_ID
10 rows selected.



SQL> drop index idx1;

Index dropped.

SQL> 
SQL> -- PCN no prefixes
SQL> exec sem_apis.create_index_on_spm_tab('idx1', 'm1',  '<http://www.example.org/works_for> +G G+ <http://www.example.org/friend_of> S', options=>' PCN_NAME=linked', network_owner=>'rdfuser', network_name=>'mynet');
PL/SQL procedure successfully completed.
SQL> 
SQL> select * from spm_index_info order by 1,2;
INDEX_NAME                               TABLE_NAME                               UNIQUENES COMPRESSION   PREFIX_LENGTH TABLESPACE_NAME
---------------------------------------- ---------------------------------------- --------- ------------- ------------- ------------------------------
KEY
------------------------------------------------------------------------------------------------------------------------------------------------------
IDX1                                     MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE DISABLED                    TBS_3
P805152655817489328,G805152655817489328,G2302183899373633243,P2302183899373633243,START_NODE_ID
MYNET#RDF_XX$MVP_M1_P4326314471650369210 MYNET#RDF_XT$MVP_M1_P4326314471650369210 NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1_UQ__DRIVES           MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1_UQ__LINKED           MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1__DRIVES_P14284748913 MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
81274755
P1428474891381274755
MYNET#RDF_XX$PCN_M1__DRIVES_P43263144716 MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
50369210
P4326314471650369210
MYNET#RDF_XX$PCN_M1__LINKED_P12357259844 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
93469672
P1235725984493469672
MYNET#RDF_XX$PCN_M1__LINKED_P23021838993 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
73633243
P2302183899373633243
MYNET#RDF_XX$PCN_M1__LINKED_P80515265581 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
7489328
P805152655817489328
MYNET#RDF_XX$SVP_M1_UQ                   MYNET#RDF_XT$SVP_M1                      UNIQUE    DISABLED                    TBS_3
START_NODE_ID
10 rows selected.
SQL> drop index idx1;
Index dropped.
SQL> 
SQL> -- MVP
SQL> exec sem_apis.create_index_on_spm_tab('idx1', 'm1',  'P G S', 'ex:drives',  prefixes=>' PREFIX : <http://wwww.nothing.org/>   PREFIX   ex:   <http://www.example.org/>', prefix_length=> 3, network_owner=>'rdfuser', network_name=>'mynet');

PL/SQL procedure successfully completed.

SQL> 
SQL> select * from spm_index_info order by 1,2;

INDEX_NAME                               TABLE_NAME                               UNIQUENES COMPRESSION   PREFIX_LENGTH TABLESPACE_NAME
---------------------------------------- ---------------------------------------- --------- ------------- ------------- ------------------------------
KEY
------------------------------------------------------------------------------------------------------------------------------------------------------
IDX1                                     MYNET#RDF_XT$MVP_M1_P4326314471650369210 NONUNIQUE ENABLED                   3 TBS_3
P4326314471650369210,G4326314471650369210,START_NODE_ID

MYNET#RDF_XX$MVP_M1_P4326314471650369210 MYNET#RDF_XT$MVP_M1_P4326314471650369210 NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1_UQ__DRIVES           MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1_UQ__LINKED           MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1__DRIVES_P14284748913 MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
81274755
P1428474891381274755
MYNET#RDF_XX$PCN_M1__DRIVES_P43263144716 MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
50369210
P4326314471650369210
MYNET#RDF_XX$PCN_M1__LINKED_P12357259844 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
93469672
P1235725984493469672
MYNET#RDF_XX$PCN_M1__LINKED_P23021838993 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
73633243
P2302183899373633243
MYNET#RDF_XX$PCN_M1__LINKED_P80515265581 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
7489328
P805152655817489328

MYNET#RDF_XX$SVP_M1_UQ                   MYNET#RDF_XT$SVP_M1                      UNIQUE    DISABLED                    TBS_3
START_NODE_ID
10 rows selected.



SQL> drop index idx1;

Index dropped.

SQL> 
SQL> -- PCN index
SQL> exec sem_apis.create_index_on_spm_tab('idx1', 'm1',  'ex:drives +G S', null,  prefixes=>' PREFIX : <http://wwww.nothing.org/>   PREFIX   ex:   <http://www.example.org/>', prefix_length=> 2, options=>' PCN_NAME=drives', network_owner=>'rdfuser', network_name=>'mynet');
PL/SQL procedure successfully completed.
SQL> 
SQL> select * from spm_index_info order by 1,2;
INDEX_NAME                               TABLE_NAME                               UNIQUENES COMPRESSION   PREFIX_LENGTH TABLESPACE_NAME
---------------------------------------- ---------------------------------------- --------- ------------- ------------- ------------------------------
KEY
------------------------------------------------------------------------------------------------------------------------------------------------------
IDX1                                     MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   2 TBS_3
P4326314471650369210,G4326314471650369210,START_NODE_ID
MYNET#RDF_XX$MVP_M1_P4326314471650369210 MYNET#RDF_XT$MVP_M1_P4326314471650369210 NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1_UQ__DRIVES           MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1_UQ__LINKED           MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1__DRIVES_P14284748913 MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
81274755
P1428474891381274755
MYNET#RDF_XX$PCN_M1__DRIVES_P43263144716 MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
50369210
P4326314471650369210
MYNET#RDF_XX$PCN_M1__LINKED_P12357259844 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
93469672
P1235725984493469672
MYNET#RDF_XX$PCN_M1__LINKED_P23021838993 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
73633243
P2302183899373633243
MYNET#RDF_XX$PCN_M1__LINKED_P80515265581 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
7489328
P805152655817489328
MYNET#RDF_XX$SVP_M1_UQ                   MYNET#RDF_XT$SVP_M1                      UNIQUE    DISABLED                    TBS_3
START_NODE_ID
10 rows selected.
SQL> drop index idx1;
Index dropped.
SQL> 
SQL> -- add value to index
SQL> -- SVP
SQL> select * from spm_index_info order by 1,2;

INDEX_NAME                               TABLE_NAME                               UNIQUENES COMPRESSION   PREFIX_LENGTH TABLESPACE_NAME
---------------------------------------- ---------------------------------------- --------- ------------- ------------- ------------------------------
KEY
------------------------------------------------------------------------------------------------------------------------------------------------------
MYNET#RDF_XX$MVP_M1_P4326314471650369210 MYNET#RDF_XT$MVP_M1_P4326314471650369210 NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1_UQ__DRIVES           MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1_UQ__LINKED           MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1__DRIVES_P14284748913 MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
81274755
P1428474891381274755
MYNET#RDF_XX$PCN_M1__DRIVES_P43263144716 MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
50369210
P4326314471650369210
MYNET#RDF_XX$PCN_M1__LINKED_P12357259844 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
93469672
P1235725984493469672
MYNET#RDF_XX$PCN_M1__LINKED_P23021838993 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
73633243
P2302183899373633243
MYNET#RDF_XX$PCN_M1__LINKED_P80515265581 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
7489328
P805152655817489328

MYNET#RDF_XX$SVP_M1_UQ                   MYNET#RDF_XT$SVP_M1                      UNIQUE    DISABLED                    TBS_3
START_NODE_ID
9 rows selected.



SQL> exec sem_apis.alter_spm_tab('m1','<http://www.example.org/friend_of>','ADD_VALUE');

PL/SQL procedure successfully completed.

SQL> exec sem_apis.alter_spm_tab('m1','<http://www.example.org/works_for>','ADD_VALUE');

PL/SQL procedure successfully completed.
SQL> exec sem_apis.alter_spm_tab('m1','<http://www.example.org/drives>','ADD_VALUE');
PL/SQL procedure successfully completed.

SQL> select * from spm_index_info order by 1,2;

INDEX_NAME                               TABLE_NAME                               UNIQUENES COMPRESSION   PREFIX_LENGTH TABLESPACE_NAME
---------------------------------------- ---------------------------------------- --------- ------------- ------------- ------------------------------
KEY
------------------------------------------------------------------------------------------------------------------------------------------------------
MYNET#RDF_XX$MVP_M1_P4326314471650369210 MYNET#RDF_XT$MVP_M1_P4326314471650369210 NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1_UQ__DRIVES           MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1_UQ__LINKED           MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1__DRIVES_P14284748913 MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
81274755
P1428474891381274755
MYNET#RDF_XX$PCN_M1__DRIVES_P43263144716 MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
50369210
P4326314471650369210
MYNET#RDF_XX$PCN_M1__LINKED_P12357259844 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
93469672
P1235725984493469672
MYNET#RDF_XX$PCN_M1__LINKED_P23021838993 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
73633243
P2302183899373633243
MYNET#RDF_XX$PCN_M1__LINKED_P80515265581 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
7489328
P805152655817489328

MYNET#RDF_XX$SVP_M1_UQ                   MYNET#RDF_XT$SVP_M1                      UNIQUE    DISABLED                    TBS_3
START_NODE_ID
9 rows selected.



SQL> 
SQL> exec sem_apis.create_index_on_spm_tab('idx1', 'm1',  'VP+ ex:works_for +G G+ +VS ex:friend_of S +VT',  prefixes=>' PREFIX : <http://wwww.nothing.org/> PREFIX ex: <http://www.example.org/>', prefix_length=> 4, network_owner=>'rdfuser', network_name=>'mynet');

PL/SQL procedure successfully completed.

SQL> 
SQL> select * from spm_index_info order by 1,2;

INDEX_NAME                               TABLE_NAME                               UNIQUENES COMPRESSION   PREFIX_LENGTH TABLESPACE_NAME
---------------------------------------- ---------------------------------------- --------- ------------- ------------- ------------------------------
KEY
------------------------------------------------------------------------------------------------------------------------------------------------------
IDX1                                     MYNET#RDF_XT$SVP_M1                      UNIQUE    ENABLED                   4 TBS_3
P805152655817489328_VNAME_PREFIX,P805152655817489328,G805152655817489328,G2302183899373633243,P805152655817489328_VNAME_SUFFIX,P2302183899373633243,ST
ART_NODE_ID,P2302183899373633243_VALUE_TYPE

MYNET#RDF_XX$MVP_M1_P4326314471650369210 MYNET#RDF_XT$MVP_M1_P4326314471650369210 NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1_UQ__DRIVES           MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1_UQ__LINKED           MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1__DRIVES_P14284748913 MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
81274755
P1428474891381274755
MYNET#RDF_XX$PCN_M1__DRIVES_P43263144716 MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
50369210
P4326314471650369210
MYNET#RDF_XX$PCN_M1__LINKED_P12357259844 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
93469672
P1235725984493469672
MYNET#RDF_XX$PCN_M1__LINKED_P23021838993 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
73633243
P2302183899373633243
MYNET#RDF_XX$PCN_M1__LINKED_P80515265581 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
7489328
P805152655817489328

MYNET#RDF_XX$SVP_M1_UQ                   MYNET#RDF_XT$SVP_M1                      UNIQUE    DISABLED                    TBS_3
START_NODE_ID
10 rows selected.



SQL> drop index idx1;

Index dropped.

SQL> 
SQL> -- PCN
SQL> exec sem_apis.create_index_on_spm_tab('idx1', 'm1',  'VP+ ex:works_for +G G+ +VS ex:friend_of S',  prefixes=>' PREFIX : <http://wwww.nothing.org/> PREFIX ex: <http://www.example.org/>', prefix_length=> 4, options=>' PCN_NAME=linked', network_owner=>'rdfuser', network_name=>'mynet');
PL/SQL procedure successfully completed.
SQL> 
SQL> select * from spm_index_info order by 1,2;
INDEX_NAME                               TABLE_NAME                               UNIQUENES COMPRESSION   PREFIX_LENGTH TABLESPACE_NAME
---------------------------------------- ---------------------------------------- --------- ------------- ------------- ------------------------------
KEY
------------------------------------------------------------------------------------------------------------------------------------------------------
IDX1                                     MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   4 TBS_3
P805152655817489328_VNAME_PREFIX,P805152655817489328,G805152655817489328,G2302183899373633243,P805152655817489328_VNAME_SUFFIX,P2302183899373633243,ST
ART_NODE_ID
MYNET#RDF_XX$MVP_M1_P4326314471650369210 MYNET#RDF_XT$MVP_M1_P4326314471650369210 NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1_UQ__DRIVES           MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1_UQ__LINKED           MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1__DRIVES_P14284748913 MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
81274755
P1428474891381274755
MYNET#RDF_XX$PCN_M1__DRIVES_P43263144716 MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
50369210
P4326314471650369210
MYNET#RDF_XX$PCN_M1__LINKED_P12357259844 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
93469672
P1235725984493469672
MYNET#RDF_XX$PCN_M1__LINKED_P23021838993 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
73633243
P2302183899373633243
MYNET#RDF_XX$PCN_M1__LINKED_P80515265581 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
7489328
P805152655817489328
MYNET#RDF_XX$SVP_M1_UQ                   MYNET#RDF_XT$SVP_M1                      UNIQUE    DISABLED                    TBS_3
START_NODE_ID
10 rows selected.
SQL> drop index idx1;
Index dropped.
SQL> 
SQL> 
SQL> exec sem_apis.create_index_on_spm_tab('idx1', 'm1',  'VP+ ex:works_for +G G+ +VS ex:friend_of S +VT',  prefixes=>' PREFIX : <http://wwww.nothing.org/> PREFIX ex: <http://www.example.org/>', prefix_length=> 4, options=>' PCN_NAME=linked', network_owner=>'rdfuser', network_name=>'mynet');
PL/SQL procedure successfully completed.
SQL> 
SQL> --MVP
SQL> select * from spm_index_info order by 1,2;

INDEX_NAME                               TABLE_NAME                               UNIQUENES COMPRESSION   PREFIX_LENGTH TABLESPACE_NAME
---------------------------------------- ---------------------------------------- --------- ------------- ------------- ------------------------------
KEY
------------------------------------------------------------------------------------------------------------------------------------------------------
IDX1                                     MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   4 TBS_3
P805152655817489328_VNAME_PREFIX,P805152655817489328,G805152655817489328,G2302183899373633243,P805152655817489328_VNAME_SUFFIX,P2302183899373633243,ST
ART_NODE_ID,P2302183899373633243_VALUE_TYPE
MYNET#RDF_XX$MVP_M1_P4326314471650369210 MYNET#RDF_XT$MVP_M1_P4326314471650369210 NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1_UQ__DRIVES           MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1_UQ__LINKED           MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
START_NODE_ID
MYNET#RDF_XX$PCN_M1__DRIVES_P14284748913 MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
81274755
P1428474891381274755
MYNET#RDF_XX$PCN_M1__DRIVES_P43263144716 MYNET#RDF_XT$PCN_M1__DRIVES              NONUNIQUE ENABLED                   1 TBS_3
50369210
P4326314471650369210
MYNET#RDF_XX$PCN_M1__LINKED_P12357259844 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
93469672
P1235725984493469672
MYNET#RDF_XX$PCN_M1__LINKED_P23021838993 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
73633243
P2302183899373633243
MYNET#RDF_XX$PCN_M1__LINKED_P80515265581 MYNET#RDF_XT$PCN_M1__LINKED              NONUNIQUE ENABLED                   1 TBS_3
7489328
P805152655817489328

MYNET#RDF_XX$SVP_M1_UQ                   MYNET#RDF_XT$SVP_M1                      UNIQUE    DISABLED                    TBS_3
START_NODE_ID
10 rows selected.
SQL> drop index idx1;
Index dropped.


1 row selected.
1.6.13.7 SPM補助表を含むモデルに対するDML操作の実行

SPM補助表ではDML操作がサポートされていますが、一部の操作によってSVP表で制約違反が発生する場合があります。

すべてのSVP、MVPおよびPCN表は、DML操作のために自動的にメンテナンスされます。
  • 削除: 削除操作の場合、MVP表から対応する行が削除されます。PCNおよびSVP表では、対応する列値は、値列を含めてNULLに設定されます。
  • 挿入: 挿入操作では、新しいサブジェクト行または対応する列値がMVP表に挿入されます(値列を含む値が存在しない場合)。SVP表およびPCN表では、既存の値がNULLの場合、新しいサブジェクト行または列値が挿入されます。既存の値とは異なる値が挿入されると、SVP表の制約違反に対してエラーが発生します。
1.6.13.8 SPM補助表を含むモデルに対するバルク・ロード操作の実行

RDFモデルに対するSPM補助表が存在する場合、そのモデルへのバルク・ロードはサポートされません。バルク・ロードを起動する前に、そのモデルのSPM補助表をすべて削除する必要があります。SEM_APIS.DROP_SPM_TABプロシージャをコールしてSPM補助表を削除できます。

1.6.13.9 SPM補助表の統計の収集

SPM補助表の統計を最新にすることは、優れた問合せパフォーマンスを得るために重要です。SEM_PERF.ANALYZE_AUX_TABLESプロシージャをコールしてSPM補助表の統計を収集できます。

1.6.13.10 SPM補助表のSPARQL問合せオプション

SPM補助表が存在する場合、SPARQL問合せではSPM補助表が自動的に使用されます。SPM表を利用するために既存のSPARQLワークロードを変更する必要はありません。ただし、SPM表の使用を微調整するために、いくつかの新しい問合せオプションおよびオプティマイザ・ヒントを使用できます。

次の問合せオプションは、SEM_MATCHのoptions引数、またはSupport for Apache JenaおよびRDFサーバーで使用されるSEM_FS_NS接頭辞で使用できます。

  • DISABLE_SPM_OPT - SPM補助表(SVP、PCNおよびMVP)を使用しません
  • DISABLE_SVP_OPT - SVP補助表を使用しません
  • DISABLE_PCN_OPT - PCN補助表を使用しません
  • DISABLE_MVP_OPT - MVP補助表を使用しません
  • DISABLE_SPM_VALUES_OPT - SPM補助表のインライン字句値を値の投影またはフィルタ評価(SVP、PCNおよびMVP)に使用しません
  • DISABLE_SPM_VALUE_PROJ_OPT - SPM補助表のインライン字句値を値の投影に使用しません(SVP、PCNおよびMVP)
  • MIN_SVP_CLUSTER_SIZE(n) - SVP表に含まれるn個以上のプロパティを参照するスター・パターン・クラスタにのみSVP補助表を使用します(デフォルトではn = 1)。
  • PREFER_PCN=T - SVPまたはPCN表を使用してトリプル・パターンを評価できる場合は、PCN表を選択します(デフォルトの動作はSVP表を使用することです)。

Support for Apache JenaおよびRDFサーバーで使用されるHINT0ヒント文字列、SEM_MATCHのオプション引数およびSEM_FS_NS接頭辞では、次の問合せオプティマイザ・ヒントを使用できます。

  • ALL_SPM_HASH / ALL_SPM_NL - SPM表(SVP、PCNおよびMVP)とのすべての結合にハッシュ/ネステッド・ループ結合を使用します
  • ALL_SVP_HASH / ALL_SVP_NL - SVP表とのすべての結合にハッシュ/ネステッド・ループ結合を使用します
  • ALL_MVP_HASH / ALL_MVP_NL - MVP表とのすべての結合にハッシュ/ネステッド・ループ結合を使用します
  • ALL_PCN_HASH / ALL_PCN_NL - PCN表とのすべての結合にハッシュ/ネステッド・ループ結合を使用します
1.6.13.11 SPM補助表を使用する場合の特別な考慮事項

SPM補助表を使用するときに考慮すべきいくつかの制限事項を次に示します。

  • SPM補助表は、単一RDFモデルでのみサポートされます。仮想モデルおよび伴意はサポートされていません。
  • SPM補助表は、Oracle Label Securityを使用するセマンティク・ネットワークではサポートされていません。
  • SPM補助表では、フラッシュバック問合せはサポートされていません。
  • SPM補助表を含むモデルはSEM_APIS.MERGE_MODELS操作で宛先モデルとして使用できません。
  • GeoSPARQLの関数またはOracle Text関数を使用するSPARQL問合せはSPM補助表を使用しません。
  • +および*プロパティ・パス式の評価ではSPM補助表は使用されません。
  • MDSYSネットワーク内のSPM補助表は、Oracle Data Pumpによってインポートまたはエクスポートされません。
  • SPM補助表は、SEM_APIS.APPEND_SEM_NETWORK_DATA SEM_APIS.MOVE_SEM_NETWORK_DATAまたはSEM_APIS.RESTORE_SEM_NETWORK_DATA操作ではサポートされていません。

1.6.14 問合せパフォーマンスのベスト・プラクティス

この項では、SEM_MATCH表関数を使用してセマンティク・データを問い合せる場合に推奨される方法について説明します。次のサブセクションが含まれます:

1.6.14.1 xsd:dateTime、xsd:dateおよびxsd:timeを含むFILTER構成要素

デフォルトでは、SEM_MATCHは、xsd:date、xsd:timeおよびxsd:dateTimeの値の比較についてXMLスキーマ標準に準拠しています。この標準に従って2つのカレンダ値のc1とc2を比較すると(c1には明示的にタイムゾーンが指定され、c2にはタイムゾーンが指定されていません)、c2は[c2-14:00, c2+14:00]という間隔に変換されます。c2-14:00 <= c1 <= c2+14:00である場合、比較は未定義となり、常にfalseに評価されます。c1がこの間隔の外部にある場合、比較は定義されます。

ただし、このような比較(タイムゾーンを持つ値とタイムゾーンを持たない値)の評価に必要な追加のロジックによって、カレンダ値が関係するFILTER構成要素を含む問合せの速度が大幅に低下する可能性があります。問合せパフォーマンスを向上させるには、SEM_MATCH表関数のoptionsパラメータにFAST_DATE_FILTER=Tを指定することによって、この追加ロジックを無効にできます。FAST_DATE_FILTER=Tを指定すると、タイムゾーンのないカレンダ値については、すべてグリニッジ標準時(GMT)と想定されます。

FAST_DATE_FILTER=Tを使用すると、(1)データセットのすべてのカレンダ値がタイムゾーンを持つ場合も、(2)データセットのすべてのカレンダ値がタイムゾーンを持たない場合も、問合せの正確性には影響ありません

1.6.14.2 型付きリテラルを含むFILTER構成要素の索引

FILTER構成要素を含むSEM_MATCH問合せの評価では、RDF_VALUE$表の順序列を使用することがよくあります。たとえば、フィルタ(?x < "1929-11-16Z"^^xsd:date)は、ORDER_DATE列を使用します。

索引を使用すると、型付きリテラルを含むフィルタ条件を含む問合せのパフォーマンスを向上させることができます。たとえば、xsd:date索引によって、フィルタ(?x < "1929-11-16Z"^^xsd:date)の評価の速度が向上する場合があります。

これらの索引をオーダー列用に作成、変更および削除するための便利なインタフェースが用意されています。詳細は、「データ型索引の使用」を参照してください。

ただし、RDF_VALUE$表にこれらの索引が存在することで、バルク・ロード操作の速度は大幅に低下する可能性があります。多くの場合、索引付きのままバルク・ロードを実行する場合と比較すると、索引を削除し、バルク・ロードを実行してから索引を再作成する方が高速です。

1.6.14.3 関係式を含むFILTER構成要素

関係式を含むFILTER構成要素には次の推奨事項が適用されます。

  • orardf:sameCanonTerm拡張関数は、すべての場合にIDベースの比較ができるので、2つのRDF用語の同一性を比較する最も効率的な方法です。

  • 標準のSPARQL機能を利用している場合、FILTER句内の2つの変数を比較するには、=または!=よりもsameTerm組込み関数の方が効率が良いため、(たとえば)可能なかぎり(?a = ?b)ではなくsameTerm(?a, ?b)を使用し、(?a != ?b)ではなく(!sameTerm(?a, ?b))を使用します。

  • FILTER式で値を比較するときは、否定の使用を減らすことによってパフォーマンスが向上する場合があります。たとえば、(?x <= "10"^^xsd:int)を評価する方が、式(!(?x > "10"^^xsd:int))を評価するよりも効率的です。

1.6.14.4 オプティマイザ統計と動的サンプリング

問合せオプティマイザに十分な統計を確保することは、優れた問合せパフォーマンスのために非常に重要です。通常は、SEM_PERF.GATHER_STATSプロシージャを使用して、セマンティク・ネットワークの基本的な統計が収集されていることを確認する必要があります(「SEM_PERFパッケージのサブプログラム」を参照)。

RDFデータ・モデル本来の柔軟性のため、静的情報ではSEM_MATCH問合せの最適実行計画が生成されない場合があります。通常、動的サンプリングでは、非常によい問合せ実行プランを生成できます。動的サンプリング・レベルは、optimizer_dynamic_samplingパラメータを使用してセッションまたはシステム・レベルで設定することも、dynamic_sampling(level) SQL問合せヒントを使用して個別の問合せレベルで設定することもできます。通常は3から6の間の動的サンプリング・レベルで試すことをお薦めします。動的サンプリングの統計の見積りの詳細は、『Oracle Database SQLチューニング・ガイド』を参照してください。

例1-98では、動的サンプリング・レベルが6のSQLヒントを使用しています。

例1-98 動的サンプリングのSQLヒント

SELECT /*+ DYNAMIC_SAMPLING(6) */ x, y
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/>
     SELECT * 
     WHERE {
      ?x :grandParentOf ?y . 
      ?x rdf:type :Male . 
      ?x :birthDate ?bd }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null, null, null, '', null, null,
    'RDFUSER', 'NET1'));
1.6.14.5 複数パーティションの問合せ

複数のセマンティク・モデル、セマンティク・モデルと伴意、および仮想モデルの使用には、次の推奨事項が適用されます。

  • 複数のセマンティク・モデルに対して、またはセマンティク・モデルと伴意に対してSEM_MATCH問合せを実行する場合は、問い合せるすべてのモデルと伴意を含む仮想モデル(「仮想モデル」を参照)を作成して、この単一の仮想モデルを問い合せると、問合せパフォーマンスが向上する可能性があります。

  • ALLOW_DUP=T問合せオプションを使用します。このオプションを使用しない場合は、RDFデータの設定済セマンティクを保持するために、問合せ処理中に高コストな(処理に関して)重複除去ステップが必要になります。ただし、このオプションを使用した場合、重複除去ステップは実行されず、パフォーマンスが大幅に向上します。

1.6.14.6 OLTP索引圧縮によるシステムの圧縮

OLTP索引圧縮がサポートされるシステム(Exadataなど)では、セマンティク・ネットワークによって使用される一部のBツリー索引の圧縮率を向上させる機能を利用できます。

たとえば、DBAまたはスキーマプライベート・ネットワークの所有者は、次のコマンドを使用して、RDF_VAL_NAMETYLITLNG_IDX索引での圧縮スキームを接頭辞圧縮からOLTP索引圧縮に変更できます。

SQL> alter index rdfuser.net1#RDF_VAL_NAMETYLITLNG_IDX rebuild compress for oltp high;
1.6.14.7 無制限のプロパティ・パス表現

+および*プロパティ・パス演算子では、可能な場合には常に深度制限検索を使用する必要があります。*および+の深度制限実装のパフォーマンスは、大規模なグラフや関連性が高いグラフにおいてはCONNECT BYベースの実装を大幅に上回ります。深度制限10がデフォルトで使用されます。どのグラフでもグラフの直径を超えた深度制限は役立ちません。深度制限の設定の詳細は、「プロパティ・パス」を参照してください。

クラス階層が非常に深いオントロジに対してrdfs:subClassOf+を使用する後方連鎖スタイルの推論は、このルールの例外になることがあります。このようなケースでは、無制限のCONNECT BYベース評価のパフォーマンスが、非常に大きな深度制限(たとえば50)の深度制限評価よりもよくなることがあります。

1.6.14.8 ネストしたループによるプロパティ・パスのプッシュダウン

あるプロパティ・パスに対して無制限のCONNECT BY評価が実行される場合で、しかもそのプロパティ・パスのトリプル・パターンの主語が変数の場合、使用される可能性が最も高いのは、CONNECT BY WITHOUT FILTERING操作です。主語になっているその変数が、問合せ実行時に限られた数の値にバインドされているだけであれば、問合せの実行時にネストしたループを用いる方法(「過負荷のサービスにおけるネストしたループによるプッシュダウン」を参照)を選ぶと良い場合があります。その場合、プロパティ・パスをSERVICE句にプッシュダウンすることができます。またOVERLOADED_NL=Tヒントを使用できます。

たとえば、次に示すような問合せを考えてみます。ここで、無制限のプロパティ・パス検索{ ?s :hasManager+ ?x }はあるものの、トリプル{ ?s :ename "ADAMS" }?sに対して取り得る値の数は限られているものとします。

select s, x
from table(sem_match(
'PREFIX : <http://scott-hr.org#>
 SELECT *
 WHERE {
   ?s :ename "ADAMS" .
   ?s :hasManager+ ?x .
 }',
sem_models('scott_hr_data'),
null,null,null,null,'  ALL_MAX_PP_DEPTH(0) ', null, null,
'RDFUSER', 'NET1'));

この問い合わせは、ネストしたループで実行されるように書き換えることができます。ここで、サービス・グラフで指定されたモデルは、SEM_MATCH呼び出しで指定されたモデルと同じである点に注意してください。

select s, x
from table(sem_match(
'PREFIX : <http://scott-hr.org#>
 SELECT *
 WHERE {
   ?s :ename "ADAMS" .
   service oram:scott_hr_data { ?s :hasManager+ ?x . }
 }',
sem_models('scott_hr_data'),
null,null,null,null,'  ALL_MAX_PP_DEPTH(0) OVERLOADED_NL=T ', null, null,
'RDFUSER', 'NET1'));

ネストしたループを用いたこの例では、{ ?s :hasManager_ ?x }?sの値ごとに1回ずつ評価され、評価のたびに定数が?sに代入されます。定数が主語の位置にあることで、CONNECT BY WITH FILTERING操作が可能になります。この操作により、通常はパフォーマンスが大幅に向上します。

1.6.14.9 グループ化と集計

MINMAXおよびGROUP_CONCAT集計では、不均一なタイプ(たとえば、MAX(?x))の入力についてSPARQLセマンティクを完全にキャプチャするために特別なロジックが必要です。均一入力タイプをコンパイル時に判別できるケース(たとえば、MAX(STR(?x)) - プレーン・リテラル入力)では、組込みSQL集計の最適化を使用できます。通常は、このような最適化によってパフォーマンスが1桁向上します。次のケースは最適化されます。

  • MIN/MAX(<plain literal>)

  • MIN/MAX(<numeric>)

  • MIN/MAX(<dateTime>)

  • GROUP_CONCAT(<plain literal>)

図1-99はMIN/MAX(<numeric>)最適化を使用しています。

例1-99 集計の最適化

SELECT dept, minSal, maxSal
  FROM TABLE(SEM_MATCH(
    'SELECT ?dept (MIN(xsd:decimal(?sal)) AS ?minSal) (MAX(xsd:decimal(?sal)) AS ?maxSal)
     WHERE
       {?x :salary ?y . 
        ?x :department ?dept }
     GROUP BY ?dept',
    SEM_Models('hr_data'),
    null, null, null, null, '', null, null,
    'RDFUSER', 'NET1'));
1.6.14.10 バインド変数の使用によるコンパイル時間の短縮

問合せによっては、問合せの実行よりも問合せのコンパイルにコストがかかることがあり、小規模な問合せでは、所定の作業量に対するスループットがこれにより制限を受ける場合があります。ワークロードの問合せが、使用される定数でのみ異なる場合、セッションのコンテキストに依存するバインド変数を使用して、SEM_MATCH問合せのコンパイル・ステップを省略できます。JDBCバインド変数およびPL/SQLバインド変数をSPARQL問合せとともに使用する方法の詳細は、SEM_APIS.SPARQL_TO_SQLによるバインド変数の使用も参照してください。

次の例では、セッション・コンテキストをユーザー定義のSPARQL関数と組み合わせて使用し、SEM_MATCH問合せを1回コンパイルしてからその問合せを異なる定数で実行する方法を示します。ここでの基本的な考え方は、セッション・コンテキストからRDF語句を読み取り、それを返すユーザー定義の関数を作成することにあります。この関数では、実行時にSEM_MATCH問合せによりRDF語句の値が読み取られます。したがって、セッション・コンテキスト変数が変化すると、まったく同じSEM_MATCH問合せでも、異なる値が生成されることになります。

conn / as sysdba;
grant create any context to testuser;

conn testuser/testuser;

create or replace package MY_CTXT_PKG as  
  procedure set_attribute(name varchar2, value varchar2);  
  function get_attribute(name varchar2) return varchar2;  
end MY_CTXT_PKG;  
/

create or replace package body MY_CTXT_PKG as  
  procedure set_attribute(  
    name varchar2,  
    value varchar2  
  ) as  
  begin  
    dbms_session.set_context(namespace => 'MY_CTXT',  
                             attribute => name,  
                             value     => value );
  end;  

  function get_attribute(  
    name varchar2  
  ) return varchar2 as  
  begin  
    return sys_context('MY_CTXT', name);  
  end;  
end MY_CTXT_PKG;  
/

create or replace function myCtxFunc(  
  params in MDSYS.SDO_RDF_TERM_LIST  
) return MDSYS.SDO_RDF_TERM  
as  
  name varchar2(4000);  
  arg  MDSYS.SDO_RDF_TERM;  
begin  
  arg := params(1);  
  name := arg.value_name;  
  return MDSYS.SDO_RDF_TERM(my_ctxt_pkg.get_attribute(name));  
end;  
/  

CREATE OR REPLACE CONTEXT MY_CTXT using TESTUSER.MY_CTXT_PKG;

-- Set a value
exec MY_CTXT_PKG.set_attribute('value','<http://www.example.org/family/Martha>');

-- Query using the function
-- Note the use of HINT0={ NON_NULL } to allow the most efficient join
SELECT s, p, o
  FROM TABLE(SEM_MATCH(
    'SELECT ?s ?p ?o
     WHERE {
       BIND (oraextf:myCtxFunc("value") # HINT0={ NON_NULL } 
             AS ?s)
       ?s ?p ?o }',
    SEM_Models('family'),
    null,
    null,
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));

-- Set another value
exec MY_CTXT_PKG.set_attribute('value','<http://www.example.org/family/Sammy>');

-- Now the same query runs for Sammy without recompiling
SELECT s, p, o
  FROM TABLE(SEM_MATCH(
    'SELECT ?s ?p ?o
     WHERE {
       BIND (oraextf:myCtxFunc("value") # HINT0={ NON_NULL } 
             AS ?s)
       ?s ?p ?o }',
    SEM_Models('family'),
    null,
    null,
    null, null, ' ', null, null,
    'RDFUSER', 'NET1'));
1.6.14.11 非NULL式ヒント

共通の変数を持つ複数のグラフ・パターンを用いて無制限になる可能性のある結合を行う場合、パフォーマンスの低下を防ぐために、NULL値を処理するより複雑な結合条件が必要になります。無制限な値は、SELECT式、バインド、OPTIONAL句およびUNIONで発生する可能性があります。多くの場合、SELECT式でNULL値が発生することは考えられません。そのような場合には、インラインのHINT0={ NON_NULL }ヒントを用いて特定のSELECT式がNULL値にならないことを明示するか、DISABLE_NULL_EXPR_JOIN問合せオプションを使用して、すべてのSELECT式でNULL以外の値が生成されることを示すことで、問合せのパフォーマンスが大幅に向上します。

次の例では、変数?fulltitleが常に結合の両端で制限されていることが、グローバルなDISABLE_NULL_EXPR_JOINヒントにより明示されています。(「インライン問合せオプティマイザ・ヒント」も参照してください。)

SELECT s, t
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/>
     SELECT * WHERE {
       { SELECT ?s (CONCAT(?title, ". ", ?fullname) AS ?fulltitle)
         WHERE { ?s :fullname ?fullname .
                 ?s :title ?title }
       }
       { SELECT ?t (CONCAT(?title, ". ", ?fname, " ", ?lname) AS ?fulltitle)
         WHERE { 
         ?t :fname ?fname .
         ?t :lname ?lname . 
         ?t :title ?title } 
       } 
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null,
    null,
    null,
    ' DISABLE_NULL_EXPR_JOIN ', null, null,
    'RDFUSER', 'NET1'));
1.6.14.12 セマンティク・ネットワーク索引

セマンティク・ネットワーク索引(セマンティク・ネットワーク索引の使用を参照)は、RDF_LINK$表の一意でないBツリー索引です。ネットワーク所有者およびDBAは、様々なSEM_APISプロシージャを使用してこれらの索引を管理できます。RDF_LINK$で索引付けする列は、索引コードによって識別されます。索引コードは、次の文字の順序です(繰返しなし): PCSGMindex_codeで使用されたこれらの文字は、RDF_LINK$の次の列に対応しています: P_VALUE_ID (述語)、CANON_END_NODE_ID (目的語)、START_NODE_ID (主語)、G_ID (グラフ)およびMODEL_ID。

問合せワークロードに適したセマンティク・ネットワーク索引のセットを持つことが重要です。バージョン19c以前では、デフォルトの索引設定はPCSGMPSCGMです。

セマンティク・ネットワーク索引の一般的な推奨事項は、次のとおりです。

  • ほとんどのSPARQL問合せには、述語がバインドされたトリプル・パターンがあるため、索引セット全体でPPCおよびPSの組合せを先行列としてカバーすることをお薦めします。このような組合せは、デフォルトの索引設定(19cのPCSGMPSCGM)によって取得されます。
  • バインドされていない述語({ ?s :ssn 1234 . ?s ?p ?o }など)を含む問合せがある場合、P以外の先頭列を持つネットワーク索引が必要になることがあります。SPCGM索引は、主語になっている変数?sに対する結合のため、この例に適しています。
  • { { <urn:abc> ?p1 ?o1 } UNION { ?s2 ?p2 <urn:abc> } }などのDESCRIBE問合せまたはDESCRIBEスタイル・パターンを実行する場合、先行するS列を持つ索引に加えて、先行するC列(CMなど)を持つネットワーク索引が必要になることがあります。
  • 選択的なFROM、FROM NAMEDまたはGRAPH句を指定したグラフ問合せがある場合、先頭にG列を持つネットワーク索引(GPCSMなど)が必要になることがあります。
  • PSCGM索引は、接頭辞圧縮が優れているために通常SPCGM索引よりも小さいので、バインドされていない述語がワークロードに含まれていない場合には、SPCGM索引をPSCGM索引に置き換えると、パフォーマンスが向上する可能性があります。
1.6.14.13 Oracle Database In-MemoryでのRDFの使用

RDF_LINK$表およびRDF_VALUE$表に格納されているRDFデータは、Oracle Database In-Memoryを使用してメモリーにロードできます。SEM_APISプロシージャを使用してRDFデータをメモリーにロードする方法の詳細は、Oracle Database In-MemoryのRDFサポートを参照してください。

一般的に、Oracle Database In-Memoryで最も一貫したパフォーマンスを得るには、RDF_VALUE$のRDF_LINK$(セマンティク・ネットワーク索引)およびRDF_VALUE$表の索引を非表示にすることをお薦めします。ただし、<NETWORK_NAME>#C_PK_VIDおよび<NETWORK_NAME>#RDF_VAL_NAMETYLITLNG_IDX索引は例外です。これらの索引設定は、次のSQLコマンドで実現できます(たとえば、NET1というセマンティク・ネットワークがRDFUSERによって所有されている場合)。

exec sem_apis.alter_sem_indexes('VISIBILITY','N', network_owner=>'RDFUSER', network_name=>'NET1');

alter index NET1#C_PK_VID visible;

alter index NET1#RDF_VAL_NAMETYLITLNG_IDX visible;

非常に選択的な問合せのパフォーマンスは、RDF_LINK$索引が非表示になる場合があるため、問合せワークロードに応じて索引の表示を試す必要がある場合があることに注意してください。

Oracle Database In-Memoryでは、このような索引設定に加えて、パラレル問合せ実行を使用することをお薦めします。多くの場合、パラレル化によるスピードアップが大幅に向上する可能性があるためです。

大規模なデータセット(100Mの3倍以上)の場合、Oracle Database In-Memoryでハッシュ・サブパーティション化されたセマンティク・ネットワークを使用することもお薦めします。ハッシュ・サブパーティション化については、セマンティク・ネットワークで説明されています。

1.6.14.14 FILTER式での言語タグの使用

言語タグに基づいて問合せ結果をフィルタリングする場合、できるかぎり、LANGMATCHESではなくLANGを使用する方が効率的です。たとえば、単純なフィルタlangMatches(lang(?x), "en")は、より効率的な評価のためにlang(?x) = "en"に置き換えることができます。格納されたRDFリテラルの言語タグは小文字に正規化されるため、このようなフィルタでは、小文字の言語タグ定数を使用する必要があります。

1.6.14.15 より効率的なFILTER評価のための型キャスト

等価以外の演算子(?x < ?yなど)を使用して2つの変数を比較するSPARQL FILTERでは、SPARQLでの型付けが弱いためにパフォーマンスが低下する可能性があります。?xおよび?yのデータ型は問合せのコンパイル時に決定できないため、実行時に複数のデータ型を比較するための複雑なロジックを使用する必要があります。

?xおよび?yがバインドされる値のデータ型がわかっている場合は、式のそれらのデータ型に?xおよび?yをキャストして、問合せコンパイル時に型がわかるようにすることをお薦めします。たとえば、次の問合せでは、より効率的な単一データ型比較のために、FILTER句で給与値をxsd:decimalにキャストします。

SELECT ?y
WHERE { 
  :emp1 :salary ?s1 . 
  ?y :salary ?s2 .
  FILTER (xsd:decimal(?s2) < xsd:decimal(?s1))
}
1.6.14.16 GeoSPARQL問合せの空間索引付け

空間索引の作成時に使用されるオプションは、GeoSPARQL問合せのパフォーマンスに大きな影響を与える可能性があります。

最も重要な2つのオプションは次のとおりです。

  • 索引のタイプ: 関数ベースまたはマテリアライズド
  • 空間参照システム: 索引に使用されるSRID

SEM_APIS.ADD_DATATYPE_INDEXは、デフォルトで関数ベースの空間索引を作成します。関数ベース索引は単純なポイント・ジオメトリには十分ですが、データセットにポリゴンまたは線ジオメトリが含まれている場合は、マテリアライズド空間索引を使用する必要があります。マテリアライズド空間索引は、SEM_APIS.ADD_DATATYPE_INDEXのオプション引数にMATERIALIZE=Tを指定することで作成できます。

空間索引に使用されるSRIDもパフォーマンスにとって重要です。オラクル社のGeoSPARQL実装は、様々な空間参照システムでエンコードされたジオメトリ・リテラルをロードできるという点で非常に柔軟です。これらのジオメトリは、索引付けおよび問合せ評価のために単一のSRIDに正規化する必要があります。索引の作成時にこの正規SRIDを指定できます。最適なパフォーマンスを得るには、ジオメトリ・リテラル間で最も一般的なSRIDを選択して、必要な座標変換を最小限に抑える必要があります。

空間索引の作成の詳細は、空間データの索引付けを参照してください。

1.6.15 SEM_MATCH使用時の特別な考慮事項

次の考慮事項は、SEM_MATCHを使用してRDFセマンティク・グラフで実行されるSPARQL問合せに適用されます。

  • 値の割当て

    • 値割り当てのソースで未定義の変数が参照されると、コンパイル時にエラーが発生します。

  • グループ化と集計

    • 非グループ化変数(グループ化に使用されないため、射影には妥当でない問合せ変数)は、値割り当てのターゲットとして再利用できません。

    • 数値以外の値は、AVGおよびSUM集計によって無視されます。

    • デフォルトでは、SEM_MATCHは、グラフ・パターンが一致しない集計問合せの場合に行を返しません。W3C仕様では、このケースでは1つのnull行が必要です。STRICT_AGG_CARD=T問合せオプションを使用すると動作がW3Cに準拠しますが、パフォーマンスがわずかに低下します。

  • ORDER BY

    • SEM_MATCHでSPARQL ORDER BYを使用する場合、取り囲んでいるSQLブロック全体を通じて目的の順序を維持するためには、格納側のSQL問合せをSEM$ROWNUMで並べ替える必要があります。

  • 数値の計算

    • ネイティブのOracleのNUMBER型はすべての演算処理のために内部的に使用され、すべての算術演算の結果はxsd:decimalとしてシリアライズされます。ネイティブのOracleのNUMBER型は、BINARY_FLOATおよびBINARY_DOUBLEよりも正確です。組込みデータ型NUMBERの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

    • ゼロで除算した場合は、バインドされていない値が生成されるのではなく、ランタイム・エラーが発生します。

  • 否定

    • 潜在的にバインドされていない変数を参照するEXISTSおよびNOT EXISTSフィルタは、次のコンテキストではサポートされません。

      • GROUP BY内の別名のない式

      • 集計への入力

      • ORDER BY内の式

      • OPTIONALグラフ・パターン内に出現しない変数も参照するOPTIONALグラフ・パターン内のFILTER式

      最初の3つのケースは、BIND句またはSELECT式を使用して変数にEXISTSまたはNOT EXISTSフィルタの結果を最初に割り当てることで実現できます。

      これらの制限は、明確にバインドされた変数のみを参照するEXISTSおよびNOT EXISTSフィルタには、当てはまりません

  • 空白ノード

    • 空白ノードは、グラフ・パターン内ではサポートされません。

    • BNODE(literal)関数は、同じリテラル引数でコールされるたびに、同じ空白ノード値を戻します。

  • プロパティ・パス

    • 無制限の演算子+および*は、パフォーマンスの理由からデフォルトでは10ホップの深度制限を使用します。深度制限を0に設定すると、この動作を完全に無制限の検索に変更できます。詳細は、「プロパティ・パス」を参照してください。

  • ロング・リテラル(CLOB)

    • SPARQLの関数と集計は、デフォルトではロング・リテラルをサポートしていません。

    • CLOB_EXP_SUPPORT=T問合せオプションを指定すると、SPARQL関数(IF、COALESCE、STRLANG、STRDT、SUBSTR、STRBEFORE、STRAFTER、CONTAINS、STRLEN、STRSTARTS、STRENDS)でのロング・リテラルのサポートが有効になります。

    • CLOB_AGG_SUPPORT=T問合せオプションを指定すると、集計(MIN、MAX、SAMPLE、GROUP_CONCAT)でのロング・リテラルのサポートが有効になります。

  • RDFリテラルの正規化

    • デフォルトでは、SPARQL関数から返されるRDFリテラルと、値割当て文(BIND、SELECT式、GROUP BY式)で使用される定数RDFリテラルは正規化されます。この動作は、SPARQL 1.1の「D-Entailment Regime」と一致しています。

    • 正規化を無効にするにはPROJ_EXACT_VALUES=T問合せオプションを使用します。

1.7 SEM_APIS.SPARQL_TO_SQL関数を使用したセマンティク・データの問合せ

SEM_APIS.SPARQL_TO_SQL関数をSEM_MATCH表関数の代わりに使用してセマンティク・データの問い合わせができます。

ノート:

共有デプロイメントでAutonomous Databaseインスタンスを使用している場合、SEM_APIS.SPARQL_TO_SQL関数には、Oracle JVMの有効化が必要です。Autonomous DatabaseインスタンスでOracle JVMを有効にするには、共有ExadataインフラストラクチャでのOracle Autonomous Databaseの使用Oracle Javaの使用を参照してください。

SEM_APIS.SPARQL_TO_SQL関数は、SEM_MATCH表関数の代替になるものとして用意されています。アプリケーション開発者は、これを利用してSPARQL問合せをSQLに翻訳することができます。これは、SEM_MATCHを実行した場合と同じSQL翻訳です。生成されたSQL翻訳は、その他のSQL文字列と同じ方法で実行可能です(たとえばPL/SQLのEXECUTE IMMEDIATEや、JavaアプリケーションのJDBC)。

SEM_APIS.SPARQL_TO_SQLに対する最初の(sparql_query)パラメータで、SPARQL問合せ文字列を指定します。これはSEM_MATCHの問合せ引数に相当します。ただしこの場合、sparql_queryは、CLOB型であり、4000バイト(VARCHARが有効になっている場合は32Kバイト)を超える長さの問合せ文字列を使用できます。その他の引数はすべて、SEM_MATCHの対応する引数とまったく同等です(「セマンティク・データに対する問合せでのSEM_MATCH表関数の使用」を参照してください)。SEM_APIS.SPARQL_TO_SQLで返される問合せ文字列によって、SEM_MATCHを同じ引数で実行したときと同じ結果の列が生成されます。

次に示すPL/SQLの一部分は、SEM_APIS.SPARQL_TO_SQL関数を使用した例です。

DECLARE
  c           sys_refcursor;
  sparql_stmt clob;
  sql_stmt    clob;
  x_value     varchar2(4000);
BEGIN
  sparql_stmt := 
    'PREFIX : <http://www.example.org/family/>
     SELECT ?x
     WHERE {
       ?x :grandParentOf ?y . 
       ?x rdf:type :Male
     }';

  sql_stmt := sem_apis.sparql_to_sql(
                sparql_stmt,
                sem_models('family'),
                SEM_Rulebases('RDFS','family_rb'),
                null,
                null,
                ' PLUS_RDFT=VC ', null, null,
                'RDFUSER', 'NET1');

  open c for 'select x$rdfterm from(' || sql_stmt || ')';
  loop
    fetch c into x_value;
    exit when c%NOTFOUND;
    
    dbms_output.put_line('x_value: ' || x_value);    
  end loop;
  close c;

END;
/

1.7.1 SEM_APIS.SPARQL_TO_SQLによるバインド変数の使用

SEM_APIS.SPARQL_TO_SQL関数を使用すると、PL/SQLおよびJDBCのバインド変数を使用できます。これは、SEM_APIS.SPARQL_TO_SQLから返されるSQL翻訳に、ANYTYPE表関数への呼出しが含まれていないためです。基本的な仕組みとして、USE_BIND_VAR=PLSQLまたはUSE_BIND_VAR=JDBC問合せオプションが指定されている場合に、単純なSPARQL BIND句が、JDBCかPL/SQLのバインド変数いずれかに変換されます。単純なSPARQL BIND句とは、BIND (<constant> AS ?var)の形式を持つものです。

バインド変数オプションが指定されている場合、SQL翻訳には、変換されたSPARQL問合せ変数各々に対して2つのバインド変数が含まれることになります。1つは値ID、もう1つはRDF語句文字列です。値ID (RDF_VALUE$表から)を1番目のバインド値として、またRDF語句文字列を2番目のバインド値として指定することで、RDF語句をSPARQL問合せ変数の代替として使用できます。パフォーマンス上の理由から、制限内のRDF語句に対する値IDが必要です。一般的なワークフローでは、RDF語句に対する値IDをRDF_VALUE$表から(またはSEM_APIS.RES2VIDで)検索し、得られたIDとRDF語句を、翻訳されたSQLにバインドします。

1つの問合せで複数の問合せ変数がバインド変数に変換されることがあります。そうした場合、バインド変数は、SPARQL問合せ文字列のSPARQL BIND句と同じ順序でSQL翻訳に現れます。つまり、1番目のBIND句に対応するIDと語句のペアが最初にバインドされ、2番目のBIND句に対応するIDと語句のペアが2番目にバインドされます。

次に示す例では、PL/SQLブロックから、SEM_APIS.SPARQL_TO_SQLに対するバインド変数が使用されています。ダミーのバインド変数?nが宣言されています。

DECLARE
  sparql_stmt clob;
  sql_stmt    clob;
  cur         sys_refcursor;
  vid         number;
  term        varchar2(4000);
  c_val       varchar2(4000);
BEGIN
  -- Add a dummy bind clause in the SPARQL statement
  sparql_stmt := 'PREFIX : <http://www.example.org/family/>
                  SELECT ?c WHERE { 
                  BIND("" as ?s)
                  ?s :parentOf ?c }';
  -- Get the SQL translation for SPARQL statement
  sql_stmt := sem_apis.sparql_to_sql(
                sparql_stmt,
                sem_models('family'),
                SEM_Rulebases('RDFS','family_rb'),
                null,
                null,' USE_BIND_VAR=PLSQL PLUS_RDFT=VC ', null, null,
                'RDFUSER', 'NET1');

  -- Execute with <http://www.example.org/family/Martha>
  term := '<http://www.example.org/family/Martha>';
  vid := sem_apis.res2vid('RDFUSER.NET1#RDF_VALUE$',term);

  dbms_output.put_line(chr(10)||'?s='||term);
  open cur for 'select c$rdfterm from('|| sql_stmt || ')' using vid,term;
  loop
    fetch cur into c_val;
    exit when cur%NOTFOUND;
    dbms_output.put_line('|-->?c='||c_val);
  end loop;
  close cur;

  -- Execute with <http://www.example.org/family/Sammy>
  term := '<http://www.example.org/family/Sammy>';
  vid := sem_apis.res2vid('RDFUSER.NET1#RDF_VALUE$',term);

  dbms_output.put_line(chr(10)||'?s='||term);
  open cur for 'select c$rdfterm from('|| sql_stmt || ')' using vid,term;
  loop
    fetch cur into c_val;
    exit when cur%NOTFOUND;
    dbms_output.put_line('|-->?c='||c_val);
  end loop;
  close cur;

END;
/

次に示す例では、Javaから、SEM_APIS.SPARQL_TO_SQLに対するバインド変数が使用されています。この例では、ヒントUSE_BIND_VAR=JDBCが使用されています。

public static void sparqlToSqlTest() {

    try {
        // Get connection
        Connection conn=DriverManager.getConnection( 
                "jdbc:oracle:thin:@localhost:1521:orcl","testuser","testuser");          

        String sparqlStmt =
            "PREFIX : http://www.example.org/family/ \n" +
            "SELECT ?c WHERE {  \n" +
            "  BIND(\"\" as ?s) \n" +
            "  ?s :parentOf ?c      \n" +
            "}";

        // Get SQL translation of SPARQL statement
        // through sem_apis.sparql_to_sql
        OracleCallableStatement ocs = (OracleCallableStatement)conn.prepareCall(
            "begin" +
            "  ? := " +
            "    sem_apis.sparql_to_sql('" +
            "      "+sparqlStmt+"'," +
            "      sem_models('family')," +
            "      SEM_Rulebases('RDFS','family_rb')," +
            "      null,null," +
            "  ' USE_BIND_VAR=JDBC PLUS_RDFT=VC " +
            " ',null,null,'RDFUSER','NET1');" +
            "end;");          
        ocs.registerOutParameter(1,Types.VARCHAR);
        ocs.execute();
        String sqlStmt = ocs.getString(1);
        ocs.close();

        // Set up statement to look up value ids
        OracleCallableStatement ocsVid = (OracleCallableStatement)conn.prepareCall(
            "begin" +
            "  ? := sem_apis.res2vid(?,?);" +
            "end;");          

        // Execute SQL setting values for a bind variable
        PreparedStatement stmt=conn.prepareStatement(sqlStmt);

        // Look up value id for first value
        long valueId = 0;
        String term = "<http://www.example.org/family/Martha>";
        ocsVid.registerOutParameter(1,Types.NUMERIC);
        ocsVid.setString(2,"RDFUSER.NET1#RDF_VALUE$");
        ocsVid.setString(3,term);
        ocsVid.execute();
        valueId = ocsVid.getLong(1);

        stmt.setLong(1, valueId);
        stmt.setString(2, term);
        ResultSet rs=stmt.executeQuery();

        // Print results
        System.out.println("\n?s="+term);
        while(rs.next()) {
            System.out.println("|-->?c=" + rs.getString("c$rdfterm"));
        }
        rs.close();

        // Execute the same query for a different URI
        // Look up value id for next value
        valueId = 0;
        term = "<http://www.example.org/family/Sammy>";
        ocsVid.registerOutParameter(1,Types.NUMERIC);
        ocsVid.setString(2,"RDFUSER.NET1#RDF_VALUE$");
        ocsVid.setString(3,term);
        ocsVid.execute();
        valueId = ocsVid.getLong(1);

        stmt.setLong(1, valueId);
        stmt.setString(2, term);
        rs=stmt.executeQuery();

        // Print results
        System.out.println("\n?s="+term);
        while(rs.next()) {
            System.out.println("|-->?c=" + rs.getString("c$rdfterm"));
        }
        rs.close();

        stmt.close();
        ocsVid.close();
        conn.close(); 

    } catch (SQLException e) {
        e.printStackTrace();
    }
}

1.7.2 SEM_MATCHとSEM_APIS.SPARQL_TO_SQLの比較

SEM_APIS.SPARQL_TO_SQL関数では、書き換え可能な表関数インタフェースを使用していることに起因するSEM_MATCH表関数に固有の制限が回避されています。具体的には、SEM_APIS.SPARQL_TO_SQLでは次のようなことが可能です。

  • 4000バイト(LONG VARCHARに対応している場合32Kバイト)を超えるSPARQL問合せ文字列の使用。

  • SEM_APIS.SPARQL_TO_SQLから返されたプレーンSQLの、読取り専用データベースに対する実行。

  • SEM_APIS.SPARQL_TO_SQLから返されたプレーンSQLの、PL/SQLおよびJDBCのバインド変数への対応。

ただし、SEM_MATCHには、SEM_APIS.SPARQL_TO_SQLにはない特有の機能があります。

  • 射影の最適化への対応。SEM_MATCHの呼び出しで、射影された変数のVAR$RDFVID列のみが選択されている場合に、この変数に対するRDF_VALUE$の結合が回避されます

  • 開始、フェッチ、クローズを行うプロシージャ型表関数の実行が必要な拡張機能への対応(SPARQL SERVICEのSERVICE_JPDWN=TおよびOVERLOADED_NL=Tオプション)。

  • SQL*Plusのようなツールを利用して対話型で問合せを実行する機能。

1.8 セマンティク・データのロードおよびエクスポート

セマンティク・データをデータベース内のモデルにロードすること、およびデータベースからステージング表へえ久ポートすることができます。

セマンティク・データをモデルにロードするには、次の1つ以上のオプションを使用します。

  • ステージング表からモデルにデータをバルク・ロードするか、追加します(各行にはRDFトリプルの主語、述語および目的語の3つのコンポーネントとオプションで名前付きグラフが含まれます)。詳細は、「ステージング表を使用したセマンティク・データのバルク・ロード」を参照してください。

    これは、大量のデータをロードする最も高速なオプションです。

  • SDO_RDF_TRIPLE_SコンストラクタをコールするSQL INSERT文を使用してアプリケーション表にデータをロードし、対応するRDFトリプル(状況によりグラフ名も含む)のセマンティク・データ・ストアに挿入します(「INSERT文を使用したセマンティク・データのロード」を参照)。

    このオプションは、小規模なデータをロードする場合に便利です

  • SEM_APIS.UPDATE_MODELを介して実行されるSPARQL更新文を含むモデルにロードされます(「セマンティク・モデルでのSPARQL更新操作のサポート」を参照)。

    このオプションは少量のデータのロードに便利です。また、より多くのデータをLOAD文を介してロードするために使用することもできます。

  • Apache JenaベースのJava APIを使用してモデルをモデルにロードします。これは、「RDF Semantic Graph Support for Apache Jena」で説明されています。

    このオプションでは、少量のデータと大量のデータをロードする方法がいくつか提供され、多くの異なるRDFシリアライズ形式がサポートされます。

ノート:

ステージング表内のUnicodeデータは、WC3N-Triple形式で指定されているように(http://www.w3.org/TR/rdf-testcases/#ntriples)エスケープする必要があります。SEM_APIS.ESCAPE_RDF_TERM関数を使用すると、ステージング表内のUnicode値をエスケープできます。たとえば、次のようにします。

create table esc_stage_tab(rdf$stc_sub, rdf$stc_pred, rdf$stc_obj);

insert /*+ append nologging parallel */ into esc_stage_tab (rdf$stc_sub, rdf$stc_pred, rdf$stc_obj)
select sem_apis.escape_rdf_term(rdf$stc_sub, options=>’ UNI_ONLY=T '), sem_apis.escape_rdf_term(rdf$stc_pred, options=>’ UNI_ONLY=T '), sem_apis.escape_rdf_term(rdf$stc_obj, options=>’ UNI_ONLY=T ')
from stage_tab; 

セマンティク・データをエクスポートする、言い換えると、セマンティク・データをステージング表に格納できるN-Triple形式またはN-Quad形式でOracle Databaseから取り出すには、「セマンティク・データのエクスポート」で説明されているSQL問合せを使用します。

ノート:

Oracle Databaseリリース12.1では、「Oracle Data Pumpを使用したセマンティク・ネットワークのエクスポートまたはインポート」の説明にあるとおり、Oracle Data Pumpユーティリティの全てのデータベース・エクスポートおよびインポートの機能を使用して、セマンティク・ネットワークのエクスポートとインポートを行うことができます。

1.8.1 ステージング表を使用したセマンティク・データのバルク・ロード

ステージング表を使用して、セマンティク・データ(およびオプションでセマンティク・データ以外の関連データ)をバルク・ロードできます。SEM_APIS.LOAD_INTO_STAGING_TABLEプロシージャ(「SEM_APISパッケージ・サブプログラム」を参照)をコールしてデータをロードします(ロード操作中に構文の正確性をチェックできます)。その後、SEM_APIS.BULK_LOAD_FROM_STAGING_TABLEプロシージャをコールして、データをステージング表からセマンティク・ストアにロードできます。(データがステージング表へのロード操作中に解析されていない場合は、SEM_APIS.BULK_LOAD_FROM_STAGING_TABLEプロシージャをコールするときにflagsパラメータにPARSEキーワードを指定する必要があります。)

次の例では、すべての必須列とそれらの列の必須名(およびロードする1つ以上のRDFトリプルにグラフ名が含まれる場合は、含まれる必要のあるオプションのRDF$STC_graph列)を含むステージング表の書式を示します。

CREATE TABLE stage_table (
                     RDF$STC_sub varchar2(4000) not null,
                     RDF$STC_pred varchar2(4000) not null,
                     RDF$STC_obj varchar2(4000) not null,
                     RDF$STC_graph varchar2(4000)
);

非セマンティク・データもロードする場合は、CREATE TABLE文に非セマンティク・データ用の追加列を指定します。非セマンティク列の名前の形式は、必須列の名前と異なる必要があります。次の例では、非セマンティク属性用の2つの追加列(SOURCEおよびID)を含むステージング表を作成します。

CREATE TABLE stage_table_with_extra_cols (
                     source VARCHAR2(4000),
                     id NUMBER,
                     RDF$STC_sub varchar2(4000) not null,
                     RDF$STC_pred varchar2(4000) not null,
                     RDF$STC_obj varchar2(4000) not null,
                     RDF$STC_graph varchar2(4000)
);

ノート:

いずれの形式のCREATE TABLE文でも、表を圧縮するためにCOMPRESS句を追加できます。このオプションにより、必要なディスク領域が減少し、バルク・ロードのパフォーマンスが向上する可能性があります。

起動側とネットワーク所有者ユーザーの両方が、ステージング表に対するSELECT権限と、アプリケーション表に対するINSERT権限を持っている必要があります。

次の項も参照してください。

1.8.1.1 ステージング表のロード

セマンティク・ストアへのロードの準備として、複数の方法でセマンティク・データをステージング表にロードできます。一般的な方法は次のとおりです。

1.8.1.1.1 SQL*Loaderを使用したステージング表へのN-Triple形式のデータのロード

SQL*Loaderユーティリティを使用して、セマンティク・データを解析し、ステージング表にロードします。Oracle Database Examplesメディアからデモ・ファイルをインストールしている場合(『Oracle Database Examplesインストレーション・ガイド』を参照)、サンプルの制御ファイル$ORACLE_HOME/md/demo/network/rdf_demos/bulkload.ctlを使用できます。入力データがN-Triple形式の場合、このファイルを変更して使用できます。

4000バイトを超える目的語はロードできません。サンプルのSQL*Loader制御ファイルを使用する場合、このような長い値を含むトリプル(行)は、自動的に拒否され、SQL*Loaderの不良ファイルに格納されます。ただし、これらの拒否された行は、SQL INSERT文を使用してアプリケーション表に挿入することによってロードできます(「INSERT文を使用したセマンティク・データのロード」を参照)。

1.8.1.1.2 外部表を使用したステージング表へのN-Quad形式のデータのロード

次の方法によって、Oracle外部表を使用してステージング表にN-Quad形式のデータ(4つの構成要素を持つ拡張トリプル)をロードできます。

  1. SEM_APIS.CREATE_SOURCE_EXTERNAL_TABLEプロシージャをコールして外部表を作成し、SQL STATEMENT ALTER TABLEを使用して、関連する1つ以上の入力ファイル名を含めるように外部表を変更します。1つ以上の入力ファイルを含むフォルダに関連付けられたディレクトリ・オブジェクトに対するREAD権限とWRITE権限を持っている必要があります。
  2. 外部表を作成したら、MDSYSユーザーに、表に対するSELECT権限とINSERT権限を付与します。
  3. SEM_APIS.LOAD_INTO_STAGING_TABLEプロシージャをコールしてステージング表に移入します。
  4. ロードが終了したら、COMMIT文を発行してトランザクションを完了します。

例1-100 外部表を使用してステージング表をロードする方法

-- Create a source external table (note: table names are case sensitive)
BEGIN
  sem_apis.create_source_external_table(
    source_table    => 'stage_table_source'
   ,def_directory   => 'DATA_DIR'
   ,bad_file        => 'CLOBrows.bad'
   );
END;
/
grant SELECT on "stage_table_source" to MDSYS;
 
-- Use ALTER TABLE to target the appropriate file(s)
alter table "stage_table_source" location ('demo_datafile.nt');
 
-- Load the staging table (note: table names are case sensitive)
BEGIN
  sem_apis.load_into_staging_table(
    staging_table => 'STAGE_TABLE'
   ,source_table  => 'stage_table_source'
   ,input_format  => 'N-QUAD');
END;
/

オブジェクトとグラフURI (結合)の長さが4000バイトを超える行は、拒否されて不良ファイルに格納されます。ただし、これらの拒否された行は、SQL INSERT文を使用してアプリケーション表に挿入することによってロードできます(「INSERT文を使用したセマンティク・データのロード」を参照)。

例1-100は、外部表を使用してステージング表をロードする方法を示します。

1.8.1.2 バルク・ロード中のイベント・トレースの記録

起動側のスキーマに表RDF$ET_TABが存在し、この表に対するINSERT権限とUPDATE権限がネットワーク所有者ユーザーに付与されている場合、SEM_APIS.BULK_LOAD_FROM_STAGING_TABLEプロシージャ実行中に実行されるタスクの一部に対するイベント・トレースが表に追加されます。バルク・ロードの問題を報告する必要がある場合は、この表の内容が役に立ちます。RDF$ET_TAB表は、次のようにして作成してください。

CREATE TABLE RDF$ET_TAB (
  proc_sid VARCHAR2(128), 
  proc_sig VARCHAR2(200),
  event_name varchar2(200),
  start_time timestamp,
  end_time timestamp,
  start_comment varchar2(1000) DEFAULT NULL,
  end_comment varchar2(1000) DEFAULT NULL
);
-- Grant privileges on RDF$ET_TAB to network owner if network owner 
-- is not the owner of RDF$ET_TAB
GRANT SELECT, INSERT, UPDATE on RDF$ET_TAB to <network_owner>;

1.8.2 INSERT文を使用したセマンティク・データのロード

INSERT文を使用してセマンティク・データをロードする場合、URIは< >(山カッコ)で、空白ノードは_:(アンダースコアとコロン)で、リテラルは" "(引用符)で囲む必要があります。URIまたは空白ノードに空白文字を使用することはできません。データを挿入するには、SDO_RDF_TRIPLE_Sコンストラクタを使用します(「トリプルを挿入するためのコンストラクタ」を参照)。アプリケーション表に対するINSERT権限を持っている必要があります。

ノート:

URIが< >で、リテラルが" "で囲まれていなくても、文はそのまま処理されます。ただし、VALUE_TYPE値の判定に余分な処理が必要とされるため、文によるロードに時間がかかります。

次の例では、RDFUSERが所有するNET1という名前のセマンティク・ネットワークを想定しています。これには、URI、空白ノード、リテラル、言語タグ付きのリテラルおよび型付きリテラルを使用した文が含まれます。

INSERT INTO nsu_data VALUES (SDO_RDF_TRIPLE_S('nsu','<http://nature.example.com/nsu/rss.rdf>',
  '<http://purl.org/rss/1.0/title>', '"Nature''s Science Update"', 'RDFUSER', 'NET1'));
INSERT INTO nsu_data VALUES (SDO_RDF_TRIPLE_S('nsu', '_:BNSEQN1001A',
  '<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>', 
  '<http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq>', 'RDFUSER', 'NET1'));
INSERT INTO nsu_data VALUES (SDO_RDF_TRIPLE_S('nsu',
  '<http://nature.example.com/cgi-taf/dynapage.taf?file=/nature/journal/v428/n6978/index.html>',
  '<http://purl.org/dc/elements/1.1/language>', '"English"@en-GB', 'RDFUSER', 'NET1'));
INSERT INTO nature VALUES (SDO_RDF_TRIPLE_S('nsu', '<http://dx.doi.org/10.1038/428004b>',
  '<http://purl.org/dc/elements/1.1/date>', '"2004-03-04"^^xsd:date', 'RDFUSER', 'NET1'));
1.8.2.1 INSERT文を使用した名前付きグラフへのデータのロード

INSERT文を使用してnull以外のグラフ名を含むRDFトリプルをロードするには、次の例に示すように、モデル名とコロン(:)区切り文字の後に、グラフ名を山カッコ(< >)で囲んで追加する必要があります。

INSERT INTO articles_rdf_data VALUES ( 
  SDO_RDF_TRIPLE_S ('articles:<http://examples.com/ns#Graph1>',
    '<http://nature.example.com/Article101>',
    '<http://purl.org/dc/elements/1.1/creator>',
    '"John Smith"', 'RDFUSER', 'NET1'));

1.8.3 セマンティク・データのエクスポート

この項には、セマンティク・データのエクスポート(つまり、セマンティク・データをステージング表に格納できるN-Triple形式またはN-Quad形式でOracle Databaseから取り出す)に関連する、次のトピックがあります。

1.8.3.1 アプリケーション表からのセマンティク・データの取得

例1-101のように、SDO_RDF_TRIPLE_Sメンバー関数を使用して、アプリケーション表からセマンティク・データを取得することができます(この例では、読みやすいように出力をフォーマットしなおしてあります)。この例では、RDFUSERというデータベース・ユーザーが所有するNET1という名前のセマンティク・ネットワークを想定しています。

例1-101 アプリケーション表からのセマンティク・データの取得

--
-- Retrieves model-graph, subject, predicate, and object
--
SQL> SELECT a.triple.GET_MODEL('RDFUSER','NET1') AS model_graph, 
            a.triple.GET_SUBJECT('RDFUSER','NET1') AS sub,
            a.triple.GET_PROPERTY('RDFUSER','NET1') pred,
            a.triple.GET_OBJ_VALUE('RDFUSER','NET1') obj
     FROM RDFUSER.NET1#RDFT_ARTICLES a;

MODEL_GRAPH
--------------------------------------------------------------------------------
SUB
--------------------------------------------------------------------------------
PRED
--------------------------------------------------------------------------------
OBJ
--------------------------------------------------------------------------------
ARTICLES
<http://nature.example.com/Article1>
<http://purl.org/dc/elements/1.1/title>
"All about XYZ"


ARTICLES
<http://nature.example.com/Article1>
<http://purl.org/dc/elements/1.1/creator>
"Jane Smith"


ARTICLES
<http://nature.example.com/Article1>
<http://purl.org/dc/terms/references>
<http://nature.example.com/Article2>


ARTICLES
<http://nature.example.com/Article1>
<http://purl.org/dc/terms/references>
<http://nature.example.com/Article3>


ARTICLES
<http://nature.example.com/Article2>
<http://purl.org/dc/elements/1.1/title>
"A review of ABC"


ARTICLES
<http://nature.example.com/Article2>
<http://purl.org/dc/elements/1.1/creator>
"Joe Bloggs"


ARTICLES
<http://nature.example.com/Article2>
<http://purl.org/dc/terms/references>
<http://nature.example.com/Article3>


7 rows selected.
1.8.3.2 RDFモデルからのセマンティク・データの取得

例1-102に示すように、SEM_MATCH表関数(「SEM_MATCH表関数を使用したセマンティク・データの問合せ」を参照)を使用して、セマンティク・データをRDFモデルから取得できます。この例では、RDFUSERというデータベース・ユーザーが所有するNET1という名前のセマンティク・ネットワークを想定しています。

例1-102 RDFモデルからのセマンティク・データの取得

--
-- Retrieves graph, subject, predicate, and object
--
SQL> select to_char(g$rdfterm) graph, to_char(x$rdfterm) sub, to_char(p$rdfterm) pred, y$rdfterm obj from table(sem_match('Select ?g ?x ?p ?y  WHERE { { GRAPH ?g {?x ?p ?y} } UNION { ?x ?p ?y }}',sem_models('articles'),null,null,null,null,' STRICT_DEFAULT=T PLUS_RDFT=T ',null,null,'RDFUSER','NET1')); 

GRAPH
------------------------------------------------------------
SUB
------------------------------------------------------------
PRED
------------------------------------------------------------
OBJ
---------------------------------------------------------------------------
<http://examples.com/ns#Graph1>
_:m99g3C687474703A2F2F6578616D706C65732E636F6D2F6E73234772617068313Egmb2
<http://purl.org/dc/elements/1.1/creator>
_:m99g3C687474703A2F2F6578616D706C65732E636F6D2F6E73234772617068313Egmb1
 
<http://examples.com/ns#Graph1>
<http://nature.example.com/Article102>
<http://purl.org/dc/elements/1.1/creator>
_:m99g3C687474703A2F2F6578616D706C65732E636F6D2F6E73234772617068313Egmb1
 
<http://examples.com/ns#Graph1>
<http://nature.example.com/Article101>
<http://purl.org/dc/elements/1.1/creator>
"John Smith"
 
<http://nature.example.com/Article1>
<http://purl.org/dc/elements/1.1/creator>
"Jane Smith"
1.8.3.3 取得した空白ノード識別子からのモデルおよびグラフ情報の削除

セマンティク・データの取得中に取得された空白ノード識別子は、例1-103のコード抜粋に示す変換を使用してモデルとグラフ情報を削除するようにトリミング可能であり、それぞれVARCHAR2 (主語コンポーネントなど)およびCLOB (目的語コンポーネントなど)データに適用できます。

例1-104に、RDFモデルからのセマンティク・データの取得に説明されているセマンティク・データ取得問合せを使用して、それぞれsub列とobj列に対して例1-103の2つの変換を使用した後に取得された結果を示します。

例1-103 アプリケーション表からのセマンティク・データの取得

--
-- Transformation on column "sub VARCHAR2" 
-- holding blank node identifier values
--
Select (case substr(sub,1,2) when '_:' then '_:' || substr(sub,instr(sub,'m',1,2)+1) else sub end) from …
--
-- Transformation on column "obj CLOB" 
-- holding blank node identifier values
--
Select (case dbms_lob.substr(obj,2,1) when '_:' then to_clob('_:' || substr(obj,instr(obj,'m',1,2)+1)) else obj end) from …

例1-104 例1-103の変換の適用による結果

--
-- Results obtained by applying transformations on the sub and pred cols
-- 
SQL> select (case substr(sub,1,2) when '_:' then '_:' || substr(sub,instr(sub,'m',1,2)+1) else sub end) sub, pred, (case dbms_lob.substr(obj,2,1) when '_:' then to_clob('_:' || substr(obj,instr(obj,'m',1,2)+1)) else obj end) obj from (select to_char(g$rdfterm) graph, to_char(x$rdfterm) sub, to_char(p$rdfterm) pred, y$rdfterm obj from table(sem_match('Select ?g ?x ?p ?y  WHERE { { GRAPH ?g {?x ?p ?y} } UNION { ?x ?p ?y }}',sem_models('articles'),null,null,null,null,' STRICT_DEFAULT=T PLUS_RDFT=T ',null,null,'RDFUSER','NET1'));

 
SUB
------------------------------------------------------------
PRED
------------------------------------------------------------
OBJ
---------------------------------------------------------------------------
_:b2
<http://purl.org/dc/elements/1.1/creator>
_:b1
 
<http://nature.example.com/Article102>
<http://purl.org/dc/elements/1.1/creator>
_:b1

1.8.4 Oracle Data Pumpを使用したセマンティク・ネットワークのエクスポートまたはインポート

Oracle Databaseリリース12.1では、Oracle Data Pumpユーティリティの全データベース・エクスポートおよびインポートの機能を使用して、セマンティク・ネットワークをエクスポートおよびインポートできます。ネットワークは、全データベース・エクスポートまたはインポートの一部として移動し、データベース全体がOracleのダンプ・ファイル(.dmp)で表現されます。

データ・ポンプを使用したセマンティク・ネットワークのエクスポートまたはインポートには、次の使用上のノートがあります。

  • インポートのターゲット・データベースには、RDFセマンティク・グラフのソフトウェアがインストールされ、既存のセマンティク・ネットワークが存在していないことが必要です。

  • ファイングレイン・アクセス制御を使用するセマンティク・ネットワーク(トリプルレベルまたはリソースレベルのOLSまたはVPD)は、エクスポートまたはインポートできません。

  • SEM_CONTAINS (MDSYS.SEMCONTEXT索引タイプ)のセマンティク・ドキュメント索引と、SEM_RELATED (MDSYS.SEM_INDEXTYPE索引タイプ)のセマンティク索引は、エクスポートの前に削除し、インポート後に再作成する必要があります。

  • エクスポートおよびインポート中は、セマンティク・ネットワーク・オブジェクトに対するデフォルトの(オブジェクトの作成直後に存在する)権限のみが保持されます。たとえばユーザーAがセマンティク・モデルMを作成し、RDFM_Mに対するSELECTをユーザーBに付与した場合、インポート後に残るのは、RDFM_Mに対するユーザーAのSELECT権限のみです。インポート後、ユーザーBには、RDFM_Mに対するSELECT権限がありません。かわりにユーザーBのSELECT権限が再度付与されます。

  • セマンティク・ネットワーク・データのエクスポートまたはインポート時には、データ・ポンプのコマンドライン・オプションtransform=oid:nを使用する必要があります。たとえば、次の形式のコマンドを使用します。

    impdp system/<password-for-system> directory=dpump_dir dumpfile=rdf.dmp full=YES version=12 transform=oid:n
    

データ・ポンプの使用方法に関する情報および例については、『Oracle Databaseユーティリティ』を参照してください。

1.8.5 セマンティク・ネットワークの移動、リストアおよび追加

SEM_APISパッケージには、セマンティク・ネットワークとの間でデータを転送するユーティリティ・プロシージャが含まれています。

セマンティク・ネットワークの内容は、ステージング・スキーマに移動できます。ステージング・スキーマ内のセマンティク・ネットワークは、(1) Oracle Data Pumpまたは同様のツールでエクスポートされるか、(2)別のセマンティク・ネットワークに追加されるか、(3)ソース・セマンティク・ネットワークにリストアされます。移動、リストアおよび追加操作の大部分では、データをコピーするためにSQL挿入ではなく、パーティション交換を使用してデータを移動します。したがって、これらの操作は非常に効率的です。

セマンティク・ネットワーク・データを移動、リストアおよび追加する手順は、次のとおりです。

移動、リストアおよび追加操作を実行する場合の特別な考慮事項

移動、リストアおよび追加操作は、次の機能を使用するセマンティク・ネットワークではサポートされていません。

  • RDF_VALUE$表のドメイン索引(空間索引など)
  • RDF用Oracle Label Security
  • ドキュメントのセマンティク索引付け
  • 増分推論

増分推論を使用するドメイン索引および伴意は、セマンティク・ネットワークを移動する前に削除し、その後のリストアまたは追加操作の後に再作成する必要があります。

追加操作に使用されるターゲット・ネットワークには、いくつかの制限が適用されます。

  • ターゲット・ネットワークのRDF条件のセットは、ソース・ネットワーク内のRDF条件のセットのサブセットである必要があります。
  • ソースおよびターゲットのセマンティク・ネットワークで使用されるモデルIDのセットは、結合解除する必要があります。
  • ソース・セマンティク・ネットワークとターゲット・セマンティク・ネットワークで使用される伴意IDは、結合解除する必要があります。
  • ソースおよびターゲットのセマンティク・ネットワークで使用されるルールベースIDのセットは、OWL2RLなどの組込みルールベースを除き、結合解除する必要があります。

このトピックの最初の2つの例は、あるデータベースから別のデータベースにMDSYS所有のセマンティク・ネットワークを移動する方法を示しています。3番目の例は、データベース内のMDSYS所有セマンティク・ネットワークを同じデータベース内のスキーマプライベート・セマンティク・ネットワークに移動(移行)する方法を示しています。

例1-105 MDSYSセマンティク・ネットワークの移動とエクスポート

この最初の例では、データ・ポンプ・エクスポートを使用して、関連するネットワーク・データを複数の.dmpファイルにエクスポートし、データを別のデータベースのセマンティク・ネットワークにインポートできます(2番目の例を参照)。

この例では、次の主要なアクションを実行します。

  1. データ・ポンプ・エクスポート操作用のディレクトリを作成します。
  2. セマンティク・ネットワークのエクスポートの出力を保持するデータベース・ユーザー(RDFEXPIMPU)を作成します。
  3. セマンティク・ネットワーク・データをRDFEXPIMPUスキーマに移動します。
  4. データ・ポンプを使用して、移動したセマンティク・ネットワーク・データをエクスポートします。
  5. データ・ポンプを使用して、セマンティク・ネットワークのモデルによって参照されるユーザー・アプリケーション表をエクスポートします。
  6. 必要に応じて、現在のネットワークのセマンティク・ネットワーク・データをリストアします。(これにより、現在のデータベースでMDSYS所有セマンティク・ネットワークを引き続き使用できます。)
conn sys/<password_for_sys> as sysdba;

-- create directory for datapump export
create directory dpump_dir as '<path_to_directory>';
grant read,write on directory dpump_dir to public;

-- create user to hold exported semantic network
grant connect, resource, unlimited tablespace to rdfexpimpu identified by <password>;

--  connect as a privileged user to move the network
conn system/<password_for_system>
-- move semantic network data to RDFEXPIMPU schema
exec sem_apis.move_sem_network_data(dest_schema=>'RDFEXPIMPU');

-- export moved network data with datapump
-- export rdfexpimpu schema
host expdp rdfexpimpu/<password> DIRECTORY=dpump_dir DUMPFILE=expuser.dmp version=12.2 logfile=export_move_sem_network_data.log

-- export any user application tables referenced by models in the semantic network
host expdp rdfuser/<password> tables=ATAB,ATAB2,ATAB3,GTAB DIRECTORY=dpump_dir DUMPFILE=exp_atabs.dmp version=12.2 logfile=export_move_atabs.log

-- export any user tables referenced in RDF Views
host expdp db_user1/<password> tables=EMP,WORKED_FOR,DEPT DIRECTORY=dpump_dir DUMPFILE=exp_rdfviewtabs.dmp version=12.2 logfile=export_move_rdfview_tabs.log

-- optionally restore the network data or drop the source semantic network
exec sem_apis.restore_sem_network_data(from_schema=>'RDFEXPIMPU');

例1-106 MDSYSセマンティク・ネットワークのインポートおよび追加

この2番目の例では、データ・ポンプ・インポートを使用して(最初の例から)関連するネットワーク・データをインポートし、必要なデータベース・ユーザーを作成し、新しいMDSYS所有セマンティク・ネットワークを作成し、インポートしたネットワーク・データを新しく作成したネットワークに追加します。

この例では、次の主要なアクションを実行します。

  1. データベース・ユーザー(RDFEXPIMPU)がデータベースに存在しない場合、セマンティク・ネットワークのエクスポートの出力を保持します。
  2. ユーザーRDFUSERおよびDB_USER1がまだデータベースに存在しない場合は、作成します。
  3. データ・ポンプを使用して、アプリケーション表、RDFビュー・コンポーネント表、および以前に移動されたセマンティク・ネットワーク・データをインポートします。
  4. インポートされたデータを追加する新しいセマンティク・ネットワークを作成します。
  5. インポートされたデータを新しく作成したセマンティク・ネットワークに追加します。
conn sys/<password_for_sys>

-- create a user to hold the imported semantic network
grant connect, resource, unlimited tablespace to rdfexpimpu identified by <password>;

-- create users that own any associated application tables
grant connect, resource, unlimited tablespace to rdfuser identified by <password>;

-- create users that own any component tables of RDF views
grant connect, resource, unlimited tablespace to db_user1 identified by <password>;

conn system/<password_for_system>

-- import any application tables
host impdp rdfuser/<password> tables=ATAB,ATAB2,ATAB3,GTAB DIRECTORY=dpump_dir DUMPFILE=exp_atabs.dmp version=12.2 logfile=import_append_sem_network_data.log

-- import any RDF view component tables
host impdp db_user1/<password> tables=EMP,WORKED_FOR,DEPT DIRECTORY=dpump_dir DUMPFILE=exp_rdfviewtabs.dmp version=12.2 logfile=import_append_rdfview_tabs.log

-- import the previously moved semantic network
host impdp rdfexpimpu/<password> DIRECTORY=dpump_dir DUMPFILE=expuser.dmp version=12.2 logfile=import_append_atabs.log

-- create a new semantic network in which to append the imported one
exec sem_apis.create_sem_network('rdf_tablespace');

-- append the imported semantic network
exec sem_apis.append_sem_network_data(from_schema=>'RDFEXPIMPU');

例1-107 MDSYSセマンティク・ネットワークの共有スキーマプライベート・セマンティク・ネットワークへの移行

この3番目の例では、SEM_APIS.MOVE_SEM_NETWORK_DATAおよびSEM_APIS.APPEND_SEM_NETWORK_DATAを使用して、既存のMDSYSセマンティク・ネットワークを共有スキーマプライベート・セマンティク・ネットワークに移行します。

この例では、次の主要なアクションを実行します。

  1. データベース・ユーザー(RDFEXPIMPU)がデータベースに存在しない場合、既存のMDSYS所有セマンティク・ネットワークを保持するデータベース・ユーザーを作成します。
  2. 既存のセマンティク・ネットワーク・データをRDFEXPIMPUスキーマに移動します。
  3. 管理データベース・ユーザー(RDFADMIN)がデータベースに存在しない場合、そのユーザー(RDFADMIN)を作成します。これは、スキーマプライベート・セマンティク・ネットワークを所有します。
  4. MY_NETという名前でRDFADMINが所有するスキーマプライベート・セマンティク・ネットワークを作成します。
  5. この新しく作成されたスキーマプライベート・ネットワークのネットワーク共有を設定します。
    1. RDFADMINにネットワーク共有権限を付与します。
    2. 古いMDSYS所有ネットワークのすべてのユーザーのネットワーク共有を有効にします。
    3. 2人の通常のデータベース・ユーザー(UDFUSERおよびDB_USER1)にアクセス権を付与します。RDFADMINに対する権限。
  6. 以前に移動したネットワーク・データを共有スキーマプライベート・セマンティク・ネットワークに追加します。
conn sys/<password_for_sys>

-- create a user to hold the moved semantic network
grant connect, resource, unlimited tablespace to rdfexpimpu identified by rdfexpimpu;

conn system/<password_for_system>

-- move the existing MDSYS semantic network
exec sem_apis.move_sem_network_data(dest_schema=>'RDFEXPIMPU');

-- drop the existing MDSYS semantic network
exec sem_apis.drop_sem_network(cascade=>true);

-- create schema-private semantic network to hold the MDSYS network data
conn sys/<password_for_sys>

-- create an admin user to own the schema-private semantic network
create user rdfadmin identified by rdfadmin;
grant connect,resource,unlimited tablespace to rdfadmin;

conn system/<password_for_system>

-- create the schema-private semantic network
exec sem_apis.create_sem_network(tablespace_name=>'rdf_tablespace',network_owner=>'RDFADMIN',network_name=>'MYNET');

-- setup network sharing for rdfadmin’s schema-private semantic network
-- first grant network sharing privileges to rdfadmin
exec sem_apis.grant_network_sharing_privs(network_owner=>'RDFADMIN');
-- now connect as rdfadmin and enable sharing for all users of the old MDSYS semantic network
conn rdfadmin/<password>
-- enable sharing for rdfadmin’s network
exec sem_apis.enable_network_sharing(network_owner=>'RDFADMIN',network_name=>'MYNET');

-- grant access privileges to RDFUSER
exec sem_apis.grant_network_access_privs(network_owner=>'RDFADMIN',network_name=>'MYNET',network_user=>'RDFUSER');
-- grant access privileges to DB_USER1
exec sem_apis.grant_network_access_privs(network_owner=>'RDFADMIN',network_name=>'MYNET',network_user=>'DB_USER1');

-- append the exported network into the shared schema-private semantic network
-- after this step, migration will be complete, and the new shared schema-private semantic network will be ready to use
conn system/<password_for_system>
exec sem_apis.append_sem_network_data(from_schema=>'RDFEXPIMPU',network_owner=>'RDFADMIN',network_name=>'MYNET');

1.8.6 未使用値のパージ

時間の経過に伴うトリプルの削除によって、RDF_VALUE$表の値のサブセットは、現在セマンティク・ネットワークに含まれるどのRDFトリプルまたはルールでも使用されなくなる可能性があります。このような使用されていない値の数が多くなり、RDF_VALUE$表の大部分を占めるようになった場合、SEM_APIS.PURGE_UNUSED_VALUESサブプログラムを使用して未使用値をパージできます。

MDSYS所有ネットワークの場合、パージする前に、ネットワーク所有者に、すべてのRDFモデルのアプリケーション表に対するSELECT権限を付与する必要があります。これを行うには、GRANTコマンドを直接使用するか、SEM_APIS.PRIVILEGE_ON_APP_TABLESサブプログラムを使用します。

パージ操作中に実行されたタスクのイベント・トレースは、RDF$ET_TAB表が起動側のスキーマに存在する場合、そこに記録できます(「バルク・ロード中のイベント・トレースの記録」を参照)。

1.9 セマンティク・ネットワーク索引の使用

セマンティク・ネットワーク索引は、一意でないBツリー索引です(セマンティク・ネットワーク索引を追加、変更および削除して、セマンティク・ネットワーク内のモデルや伴意とともに使用できます)。

このような索引を使用すると、ネットワーク内のモデルや伴意に対するSEM_MATCH問合せのパフォーマンスを調整できます。任意の索引と同様に、セマンティク・ネットワーク索引によって、問合せワークロードに適合する索引ベースのアクセスが可能になります。これによって、次の例のシナリオのようにパフォーマンスが大幅に向上する可能性があります。

  • グラフ・パターンが'{<John> ?p <Mary>}'の場合は、1つ以上のターゲット・モデルに対して、対応する伴意で(問合せで使用される場合)、便利な'CSPGM''または'SCPGM'索引を使用できます。

  • グラフ・パターンが'{?x <talksTo> ?y . ?z ?p ?y}'の場合は、Cを主要なキーとして使用して(たとえば'CPSGM')、関連する1つ以上のモデルおよび伴意に便利なセマンティク・ネットワーク索引を用意できます。

ただし、セマンティク・ネットワーク索引を使用すると、DML、ロードおよび推論操作に必要な時間が増加して、パフォーマンス全体が影響を受ける可能性があります。

セマンティク・ネットワーク索引は、次のサブプログラムを使用して作成および管理できます。

これらのサブプログラムはすべてindex_codeパラメータを持ち、このパラメータには、PCSGMを任意の順序(繰返しなし)で含めることができます。index_code内で使用されたこれらの文字は、ビューSEMM_*およびSEMI_*の列P_VALUE_ID、CANON_END_NODE_ID、START_NODE_ID、G_IDおよびMODEL_IDに対応しています。

SEM_APIS.ADD_SEM_INDEXプロシージャは、セマンティク・ネットワーク索引を作成し、これにより、既存のモデルおよび伴意それぞれに対して、一意でないBツリー索引がUNUSABLEステータスで作成されます。索引の名前はRDF_LNK_<index_code>_IDXで、索引はネットワーク所有者によって所有されます。この操作が許可されるのは、起動者がDBAロールを持つか、ネットワーク所有者である場合のみです。次の例では、キー<P_VALUE_ID, START_NODE_ID, CANON_END_NODE_ID, G_ID, MODEL_ID>を使用してPSCGM索引を作成しています。

EXECUTE SEM_APIS.ADD_SEM_INDEX('PSCGM' network_owner=>'RDFUSER', network_name=>'NET1');

セマンティク・ネットワーク索引を作成すると、それぞれ対応する一意ではないBツリー索引がUNUSABLEステータスになります。これは、この検索の使用による長時間の処理や大量のリソース消費、さらにはそれらに伴って発生する索引のメンテナンス操作により望ましくないパフォーマンス・コストが発生する可能性があるからです。SEM_APIS.ALTER_SEM_INDEX_ON_MODELおよびSEM_APIS.ALTER_SEM_INDEX_ON_ENTAILMENTプロシージャをコールしたときにcommandパラメータとして'REBUILD'または'UNUSABLE'を指定することで、所有する特定のモデルや伴意でセマンティク・ネットワーク索引を使用または不使用に設定できます。セマンティク・ネットワーク索引を使用または不使用にして、パフォーマンスに違いが出るか確認できます。たとえば、次の文はPSCGM索引をFAMILYモデルで使用できるように設定します。

EXECUTE SEM_APIS.ALTER_SEM_INDEX_ON_MODEL('FAMILY','PSCGM','REBUILD' network_owner=>'RDFUSER', network_name=>'NET1');

また、次の点にも注意してください。

  • 自分で作成したセマンティク・ネットワーク索引とは無関係に、セマンティク・ネットワークが作成されると自動的に作成される索引の1つに、この項に示したサブプログラムをコールするときにindex_code'PSCGM'と指定することで管理できる索引があります。

  • 新規のモデルまたは新規の伴意を作成すると、セマンティク・ネットワーク索引ごとに一意でない新規のBツリー索引が作成されますが、このようなBツリー索引はいずれも、USABLEステータスになります。

  • (index_code値に'M'を含めることにより)セマンティク・ネットワーク索引キーにMODEL_ID列を含めると、問合せのパフォーマンスが向上することがあります。特に、仮想モデルを使用する場合はこの操作が有効です。

1.9.1 SEM_NETWORK_INDEX_INFOビュー

モデルと伴意のすべてのネットワーク索引に関する情報は、SEM_NETWORK_INDEX_INFOビューに保持されます(表1-24に、このビューの列(一部のリスト)を示します(1つの行が1つのネットワーク索引に対応します))。

表1-24 SEM_NETWORK_INDEX_INFOビューの列(一部のリスト)

列名 データ型 説明

NAME

VARCHAR2(30)

RDFモデルまたは伴意の名前

TYPE

VARCHAR2(10)

索引が構築されるオブジェクトのタイプ: MODELENTAILMENTまたはNETWORK

ID

NUMBER

モデルまたは伴意のID番号、またはネットワークに対する索引の場合は0 (ゼロ)

INDEX_CODE

VARCHAR2(25)

索引のコード(たとえばPSCGM)

INDEX_NAME

VARCHAR2(30)

索引の名前(たとえば、RDF_LNK_PSCGM_IDX)

LAST_REFRESH

TIMESTAMP(6)WITH TIME ZONE

このコンテンツがリフレッシュされた最終時刻のタイムスタンプ

表1-24に示した列の他に、SEM_NETWORK_INDEX_INFOビューには、ALL_INDEXESおよびALL_IND_PARTITIONSビュー(どちらも『Oracle Databaseリファレンス』を参照)から得られる次の列を含みます。

  • ALL_INDEXESビュー: UNIQUENESS、COMPRESSION、PREFIX_LENGTH

  • ALL_IND_PARTITIONSビュー: STATUS、TABLESPACE_NAME、BLEVEL、LEAF_BLOCKS、NUM_ROWS、DISTINCT_KEYS、AVG_LEAF_BLOCKS_PER_KEY、AVG_DATA_BLOCKS_PER_KEY、CLUSTERING_FACTOR、SAMPLE_SIZE、LAST_ANALYZED

SEM_NETWORK_INDEX_INFOビューの情報は失効している場合があることに注意してください。この情報をリフレッシュするには、SEM_APIS.REFRESH_SEM_NETWORK_INDEX_INFOプロシージャを使用します。

1.10 データ型索引の使用

データ型索引は、セマンティク・ネットワークに格納される型付きリテラルの値の索引です。

この索引を使用すると、特定のタイプのFILTER式を含むSEM_MATCH問合せのパフォーマンスが大幅に向上する場合があります。たとえば、xsd:dateTimeリテラルのデータ型索引によって、フィルタ(?x < "1929-11-16T13:45:00Z"^^xsd:dateTime)の評価の速度が向上する場合があります。索引を作成できるいくつかのデータ型を、表1-25に示します。

表1-25 データ型索引のデータ型

データ型URI Oracle型 索引型

http://www.w3.org/2001/XMLSchema#decimal

NUMBER

一意でないBツリー(xsd:floatxsd:doublexsd:decimal などのすべてのxsd数値型とそのすべてのサブタイプに対応する単一の索引を作成)

http://www.w3.org/2001/XMLSchema#string

VARCHAR2

一意ではないBツリー(xsd:string型付きリテラルとプレーン・リテラルに対して単一の索引を作成します)

http://www.w3.org/2001/XMLSchema#time

TIMESTAMP WITH TIMEZONE

一意でないBツリー

http://www.w3.org/2001/XMLSchema#date

TIMESTAMP WITH TIMEZONE

一意でないBツリー

http://www.w3.org/2001/XMLSchema#dateTime

TIMESTAMP WITH TIMEZONE

一意でないBツリー

http://xmlns.oracle.com/rdf/text

(該当なし)

CTXSYS.CONTEXT

http://xmlns.oracle.com/rdf/geo/WKTLiteral

SDO_GEOMETRY

MDSYS.SPATIAL_INDEX

http://www.opengis.net/geosparql#wktLiteral

SDO_GEOMETRY

MDSYS.SPATIAL_INDEX

http://www.opengis.net/geosparql#gmlLiteral

SDO_GEOMETRY

MDSYS.SPATIAL_INDEX

http://xmlns.oracle.com/rdf/like

VARCHAR2

一意でないBツリー

データ型索引が適切かどうかは、問合せのワークロードに応じて異なります。xsdデータ型でのデータ型索引は、変数を定数値と比較するフィルタに使用可能であり、特に、非常に選択的なフィルタ条件を持つ選択的でないグラフ・パターンが問合せに含まれる場合に役立ちます。適切なデータ型索引は、空間フィルタまたはテキスト・フィルタを使用する問合せに必要です。

データ型索引によって問合せパフォーマンスは向上しますが、徐々に増加する索引のメンテナンスによって、セマンティク・ネットワークに対するDMLおよびバルク・ロード操作のパフォーマンスが低下する可能性があります。バルク・ロード操作では、通常、データ型索引を削除し、バルク・ロードを実行してからデータ型索引を再作成する方が高速です。

以下のプロシージャを使ってデータ型索引を追加、変更、削除することができます。これらのプロシージャの説明は、「SEM_APISパッケージのサブプログラム」に記載されています。

既存のデータ型索引に関する情報は、SEM_DTYPE_INDEX_INFOビューに保持されます(表1-26に示す列、およびデータ型索引ごとに1つの行が含まれます)。

表1-26 SEM_DTYPE_INDEX_INFOビューの列

列名 データ型 説明

DATATYPE

VARCHAR2(51)

データ型URI

INDEX_NAME

VARCHAR2(30)

索引の名前

STATUS

VARCHAR2(8)

索引のステータス: USABLEまたはUNUSABLE

TABLESPACE_NAME

VARCHAR2(30)

索引の表領域

FUNCIDX_STATUS

VARCHAR2(8)

関数ベース索引の状態。取り得る値は、NULLENABLEDまたはDISABLEDです。

例1-108に示すとおり、誕生日が1929年11月16日より前のすべての祖父を見つける問合せの評価中にデータ型索引を使用するように、HINT0ヒントを使用できます。

例1-108 HINT0を使用してデータ型索引が使用されるようにする方法

SELECT x, y
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/>
     SELECT ?x ?y 
     WHERE {?x :grandParentOf ?y . ?x rdf:type :Male . ?x :birthDate ?bd
       FILTER (?bd <= "1929-11-15T23:59:59Z"^^xsd:dateTime) }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    
    null, null, null, 
    'HINT0={ LEADING(?bd) INDEX(?bd rdf_v$dateTime_idx) } 
             FAST_DATE_FILTER=T', 
    null, null,
    'RDFUSER', 'NET1' ));

1.11 セマンティク・モデルおよびセマンティク・ネットワークの統計の管理

統計は、Oracle Databaseに格納されているセマンティク・データに対するSPARQL問合せおよびOWL推論のパフォーマンスに重要な意味を持ちます。

Oracle Databaseリリース11gでは、セマンティク・データを分析して、統計を最新に保持するために、SEM_APIS.ANALYZE_MODELSEM_APIS.ANALYZE_ENTAILMENTおよびSEM_PERF.GATHER_STATSが導入されています。これらのAPIは使用しやすく、表およびパーティション統計の内部的な詳細に関心がない一般ユーザーを対象としています。

次のサブプログラムを使用して、モデルおよび伴意の統計をエクスポート、インポート、設定および削除したり、ネットワーク統計をエクスポート、インポートおよび削除することができます。

この項では、セマンティク・モデルとセマンティク・ネットワークの統計の管理に関連する、次の内容について説明します。

1.11.1 モデル・レベルでの統計の保存

既存のモデルに対する問合せおよび推論が効率的に実行された場合、モデルの所有者として、既存のモデルの統計を保存できます。

-- Login as the model owner (for example, SCOTT)
-- Create a stats table. This is required.
execute dbms_stats.create_stat_table('scott','rdf_stat_tab');
 
-- You must grant access to MDSYS
SQL> grant select, insert, delete, update on scott.rdf_stat_tab to MDSYS;
 
-- Now export the statistics of model TEST
execute sem_apis.export_model_stats('TEST','rdf_stat_tab', 'model_stat_saved_on_AUG_10', true, 'SCOTT', 'OBJECT_STATS', network_owner=>'RDFUSER', network_name=>'NET1');

また、SEM_APIS.EXPORT_ENTAILMENT_STATS を使用して、伴意の統計(伴意グラフ)を保存できます。

execute sem_apis.create_entailment('test_inf',sem_models('test'),sem_rulebases('owl2rl'),0,null,network_owner=>'RDFUSER',network_name=>'NET1');
PL/SQL procedure successfully completed.
 
execute sem_apis.export_entailment_stats('TEST_INF','rdf_stat_tab', 'inf_stat_saved_on_AUG_10', true, 'SCOTT', 'OBJECT_STATS', network_owner=>'RDFUSER', network_name=>'NET1');

1.11.2 モデル・レベルでの統計のリストア

モデルの所有者として、以前にSEM_APIS.EXPORT_MODEL_STATS に保存した統計をリストアできます。これは、このモデルに更新が割り当てられ、統計が再収集された場合に必要となることがあります。統計に変更があると既存のSPARQL問合せの計画変更が生じることがあり、このような計画変更を望まない場合には、古いセットの統計をリストアできます。

execute sem_apis.import_model_stats('TEST','rdf_stat_tab', 'model_stat_saved_on_AUG_10', true, 'SCOTT', false, true, 'OBJECT_STATS', network_owner=>'RDFUSER', network_name=>'NET1');

また、SEM_APIS.IMPORT_ENTAILMENT_STATS を使用して、伴意の統計(伴意グラフ)をリストアできます。

execute sem_apis.import_entailment_stats('TEST','rdf_stat_tab', 'inf_stat_saved_on_AUG_10', true, 'SCOTT', false, true, 'OBJECT_STATS', network_owner=>'RDFUSER', network_name=>'NET1');

1.11.3 ネットワーク・レベルでの統計の保存

統計はネットワーク・レベルで保存できます。

-- Network owners and DBAs have privileges to gather network-wide 
-- statistics with the SEM_PERF package.
--
-- This example assumes a schema-private semantic network named NET1
-- owned by RDFUSER.
--

conn RDFUSER/<password>
 
execute dbms_stats.create_stat_table('RDFUSER','rdf_stat_tab');
-- The next grant is only necessary if using the MDSYS semantic network
grant select, insert, delete, update on RDFUSER.rdf_stat_tab to MDSYS;
 
--
-- This API call will save the statistics of both the RDF_VALUE$ table
-- and RDF_LINK$ table
--
execute sem_perf.export_network_stats('rdf_stat_tab', 'NETWORK_ALL_saved_on_Aug_10', true, 'RDFUSER', 'OBJECT_STATS', network_owner=>'RDFUSER', network_name=>'NET1');
 
--
-- Alternatively, you can save statistics of only the RDF_VALUE$ table
--
execute sem_perf.export_network_stats('rdf_stat_tab', 'NETWORK_VALUE_TAB_saved_on_Aug_10', true, 'RDFUSER', 'OBJECT_STATS', options=> mdsys.sdo_rdf.VALUE_TAB_ONLY, network_owner=>'RDFUSER', network_name=>'NET1');
 
--
-- Or, you can save statistics of only the RDF_LINK$ table
--
execute sem_perf.export_network_stats('rdf_stat_tab', 'NETWORK_LINK_TAB_saved_on_Aug_10', true, 'RDFUSER', 'OBJECT_STATS', options=> mdsys.sdo_rdf.LINK_TAB_ONLY, network_owner=>'RDFUSER', network_name=>'NET1');

1.11.4 ネットワーク・レベルでの拡張統計の削除

デフォルトでは、SEM_PERF.GATHER_STATSが、RDF_LINK$表の列グループを使用して拡張統計を作成します。ネットワーク・レベルでの統計の保存の特権ユーザーは、SEM_PERF.DROP_EXTENDED_STATSを使用して、これらの列グループを削除できます。

connect RDFUSER/<password>
execute sem_perf.drop_extended_stats(network_owner=>'RDFUSER', network_name=>'NET1');

『Oracle Database SQLチューニング・ガイド』を参照して、拡張統計の管理の詳細も確認してください。

1.11.5 ネットワーク・レベルでの統計のリストア

「ネットワーク・レベルでの統計の保存」の特権ユーザーは、SEM_PERF.IMPORT_NETWORK_STATSを使用して、ネットワーク・レベル統計をリストアできます。

conn RDFUSER/<password>
 
execute sem_perf.import_network_stats('rdf_stat_tab', 'NETWORK_ALL_saved_on_Aug_10', true, 'RDFUSER', false, true, 'OBJECT_STATS', network_owner=>'RDFUSER', network_name=>'NET1');

1.11.6 モデル・レベルでの統計の設定

モデルの所有者として、このモデルの統計を手動で調整できます。(ただし、統計を調整する前に、統計を必要に応じてリストアできるように先に保存しておく必要があります。)次の例では、モデルの行数とブロック数の2つのメトリックを設定します。

execute sem_apis.set_model_stats('TEST', numrows=>10, numblks=>1,no_invalidate=>false,network_owner=>'RDFUSER',network_name=>'NET1');

また、SEM_APIS.SET_ENTAILMENT_STATS を使用して、伴意の統計を設定できます。

execute sem_apis.set_entailment_stats('TEST_INF', numrows=>10, numblks=>1,no_invalidate=>false,network_owner=>'RDFUSER',network_name=>'NET1');

1.11.7 モデル・レベルでの統計の削除

統計の削除も実行計画に影響を及ぼすことがあります。モデルの所有者として、モデルの統計を削除できます。

execute sem_apis.delete_model_stats('TEST', no_invalidate=> false, network_owner=>'RDFUSER', network_name=>'NET1');

また、SEM_APIS.DELETE_ENTAILMENT_STATSを使用して、伴意の統計を削除できます。(ただし、モデルまたは伴意の統計を削除する前に、統計を必要に応じてリストアできるように先に保存しておく必要があります。)

execute sem_apis.delete_entailment_stats('TEST_INF', no_invalidate=> false, network_owner=>'RDFUSER', network_name=>'NET1');

1.12 セマンティク・モデルに対するSPARQL更新操作のサポート

Oracle Databaseリリース12.2では、セマンティク・モデルに対するSPARQL更新操作が可能になりました。

ノート:

共有デプロイメントでAutonomous Databaseインスタンスを使用している場合、モデルにSPARQL更新操作を実行するには、Oracle JVMの有効化が必要です。Autonomous DatabaseインスタンスでOracle JVMを有効にするには、共有ExadataインフラストラクチャでのOracle Autonomous Databaseの使用Oracle Javaの使用を参照してください。

W3Cは、RDFグラフに対する更新言語であるSPARQL 1.1更新(https://www.w3.org/TR/2013/REC-sparql11-update-20130321/)を定めています。SPARQL 1.1更新は、SEM_APIS.UPDATE_MODELプロシージャを通じて、Oracle Databaseでサポートされています。

SPARQL更新操作を実行するには、前提となる条件がいくつかあります。

  • SEM_APIS.UPDATE_MODELプロシージャを使用することになる各ユーザーのスキーマで、SEM_APIS.CREATE_SPARQL_UPDATE_TABLESプロシージャを実行しておく必要があります。

  • SEM_APIS.UPDATE_MODELプロシージャを使用してモデルを更新するユーザーには、apply_modelモデルに関連するアプリケーション表へのINSERT権限が必要であり、ネットワーク所有者ユーザーには、その表に対するINSERT権限が付与されている必要があります(たとえばMDSYS所有ネットワークの場合はGRANT INSERT on APP_TAB1 to MDSYS;)。

    ここで、アプリケーション表は、モデルに対するセマンティク・データを参照している表です。

  • • LOAD操作を実行するには、ユーザーにCREATE ANY DIRECTORY権限およびDROP ANY DIRECTORY権限があるか、optionsパラメータで名前が指定されている既存のディレクトリ・オブジェクトに対するREAD権限が付与されている必要があります。

次に、RDFモデルに対する更新操作の例をいくつか示します。この例では、RDFUSERというデータベース・ユーザーが所有する、NET1という名前のスキーマプライベート・セマンティク・ネットワークを想定しています。

例1-109 INSERT DATA操作

これは、electronicsモデルのデフォルト・グラフに複数のトリプルを挿入するINSERT DATA操作の例です。

-- Dataset before operation:
#Empty default graph
-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/> 
    INSERT DATA {
       :camera1 :name "Camera 1" .
       :camera1 :price 120 .
       :camera1 :cameraType :Camera .
       :camera2 :name "Camera 2" .
       :camera2 :price 150 .
       :camera2 :cameraType :Camera .
      } ', 
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera1 :name "Camera 1";
         :price 120;
         :cameraType :Camera .
:camera2 :name "Camera 2"; 
         :price 150;
         :cameraType :Camera .

例1-110 DELETE DATA操作

これは、electronicsモデルのデフォルト・グラフからトリプルを1つ削除するDELETE DATA操作の例です。

-- Dataset before operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera1 :name "Camera 1";
         :price 120;
         :cameraType :Camera .
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/> 
    DELETE DATA { :camera1 :price 120 . } ', 
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera1 :name "Camera 1";
         :cameraType :Camera .
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .

例1-111 デフォルト・グラフに対するDELETE操作およびINSERT操作

この例ではDELETE操作およびINSERT操作を行っています。:camera1:cameraTypeが、:digitalCameraに更新されています。

-- Dataset before operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera1 :name "Camera 1";
         :cameraType :Camera .
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .

-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/> 
    DELETE { :camera1 :cameraType ?type . } 
    INSERT { :camera1 :cameraType :digitalCamera . } 
    WHERE  { :camera1 :cameraType ?type . }', 
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera1 :name "Camera 1";
         :cameraType :digitalCamera .
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .

例1-112 デフォルト・グラフおよび名前付きグラフに対するDELETE操作およびINSERT操作

グラフは、DELETEおよびINSERTテンプレートで指定することも、WHERE句の中で指定することもできます。この例では、デジタル・カメラに対応するすべてのトリプルを、デフォルト・グラフから:digitalCamerasというグラフへ移動します。

-- Dataset before operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera1 :name "Camera 1";
         :cameraType :digitalCamera .
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Empty graph :digitalCameras

-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/> 
    DELETE { ?s ?p ?o } 
    INSERT { graph :digitalCameras { ?s ?p ?o } }
    WHERE  { ?s :cameraType :digitalCamera .
             ?s ?p ?o }', 
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}

例1-113 INSERT WHERE操作およびDELETE WHERE操作

DELETE操作またはINSERT操作から、DELETEテンプレートまたはINSERTテンプレートのいずれかを削除できます。さらに、DELETEに続くテンプレートは、WHEREパターンをDELETEテンプレートとして使用するためのショートカットとして省略できます。この例では、INSERT WHERE文を使用して、:digitalCamerasグラフのコンテンツを:camerasグラフに挿入しています。また、構文ショートカットを用いたDELETE WHERE文を使用して、:camerasグラフからすべてのコンテンツを削除しています。


-- INSERT WHERE
-- Dataset before operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}
#Empty graph :cameras

-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/> 
    INSERT { graph :cameras { ?s ?p ?o } }
    WHERE  { graph :digitalCameras { ?s ?p ?o } }', 
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}

-- DELETE WHERE
-- Dataset before operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}

-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/> 
    DELETE WHERE { graph :cameras { ?s ?p ?o } }', 
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}
#Empty graph :cameras

例1-114 COPY操作

この例ではCOPY操作を行っています。デフォルト・グラフから、すべてのデータが:camerasグラフに挿入されます。:camerasに既存データがある場合、そのデータは挿入前に削除されます。

-- Dataset before operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
  :camera3 :name "Camera 3" .
}

-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/>
    COPY DEFAULT TO GRAPH :cameras', 
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
  :camera1 :name "Camera 1"; 
           :cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
  :camera2 :name "Camera 2";
           :price 150;
           :cameraType :Camera .
}

例1-115 ADD操作

この例では、:digitalCamerasグラフのデータすべてを、:camerasグラフへ追加しています。

-- Dataset before operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
  :camera2 :name "Camera 2";
           :price 150;
           :cameraType :Camera .
}

-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/>
    ADD GRAPH :digitalCameras TO GRAPH :cameras', 
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
  :camera2 :name "Camera 2";
           :price 150;
           :cameraType :Camera .
}

例1-116 MOVE操作

この例では、:digitalCamerasグラフのデータすべてを、:digCamグラフへ移動しています。

-- Dataset before operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
  :camera2 :name "Camera 2";
           :price 150;
           :cameraType :Camera .
}
#Graph :digCam
GRAPH :digCam {
  :camera4 :cameraType :digCamera .
}

-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/>
    MOVE GRAPH :digitalCameras TO GRAPH :digCam', 
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2" .
         :camera2 :price 150 .
         :camera2 :cameraType :Camera .
#Empty graph :digitalCameras
#Graph :cameras
GRAPH :cameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
  :camera2 :name "Camera 2";
           :price 150;
           :cameraType :Camera .
}
#Graph :digCam
GRAPH :digCam {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}

例1-117 CLEAR操作

この例では、CLEAR操作を実行して、デフォルト・グラフのトリプルすべてを削除しています。RDFモデルには空のグラフは保存されないため、CLEAR操作はいつも成功します。また、この操作はDROP操作と等価です。(同じ理由で、CREATE操作はRDFモデルに何の影響も与えません。)

-- Dataset before operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Empty graph :digitalCameras
#Graph :cameras
GRAPH :cameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera 
  :camera2 :name "Camera 2";
           :price 150;
           :cameraType :Camera .
}
#Graph :digCam
GRAPH :digCam {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}

-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'CLEAR DEFAULT ', 
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Empty Default graph
#Empty graph :digitalCameras
#Graph :cameras
GRAPH :cameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
  :camera2 :name "Camera 2";
           :price 150;
           :cameraType :Camera .
}
#Graph :digCam
GRAPH :digCam {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}

例1-118 LOAD操作

N-Triple、N-Quad、TurtleおよびTrigのファイルを、ローカル・ファイル・システムから、LOAD操作によってロードできます。より単純なN-TripleおよびN-Quad形式の方が、TurtleおよびTrigより速くロードできることに注意してください。オプションのINTO句を使用して、特定の名前付きグラフにファイルをロードできます。LOAD操作を実行するには、ユーザーに(1) CREATE ANY DIRECTORY権限およびDROP ANY DIRECTORY権限があるか、または(2) UPDATE_MODELのoptionsパラメータで既存のディレクトリ・オブジェクトの名前を指定する必要があります。この例では、N-Quadファイル/home/oracle/example.nqを、セマンティク・モデルにロードしています。

なお、N-QuadまたはTrigファイルでINTO句を使用すると、そのファイルにある名前付きグラフの情報は、すべて上書きされます。この例では、INTO GRAPH :camerasにより、最初のクワッドに対して:myGraphが上書きされるため、代わりにこのクワッドのトリプル・コンポーネントである主語、プロパティ、目的語が、:camerasグラフに挿入されます。

-- Datafile: /home/oracle/example.nq
<http://www.example.org/electronics/camera3> <http://www.example.org/electronics/name> "Camera 3" <http://www.example.org/electronics/myGraph> .
<http://www.example.org/electronics/camera3> <http://www.example.org/electronics/price> "125"^^<http://www.w3.org/2001/XMLSchema#decimal> .

-- Dataset before operation:
#Graph :cameras
GRAPH :cameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
  :camera2 :name "Camera 2";
           :price 150;
           :cameraType :Camera .
}
#Graph :digCam
GRAPH :digCam {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}

-- Update operation:
CREATE OR REPLACE DIRECTORY MY_DIR AS '/home/oracle';

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/>
    LOAD <file:///example.nq> INTO GRAPH :cameras',
   options=>'LOAD_DIR={MY_DIR}', 
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Graph :cameras
GRAPH :cameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
  :camera2 :name "Camera 2";
           :price 150;
           :cameraType :Camera .
  :camera3 :name "Camera 3";
           :price 125.
}
#Graph :digCam
GRAPH :digCam {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}

1回のLOAD操作で、同じディレクトリのファイルを複数、並行してロードできます。追加のN-TripleまたはN-Quadのファイルをロードするために、LOAD_OPTIONSヒントを使用できます。ロードの並列度は、options文字列のPARALLEL(n)で指定できます。次の例では、ファイル/home/oracle/example1.nq/home/oracle/example2.nqおよび/home/oracle/example3.nqを、セマンティク・モデルにロードする方法を示します。この例では、並列度3が使用されています。

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/>
    LOAD <file:///example1.nq>',
   options=> ' PARALLEL(3) LOAD_OPTIONS={ example2.nq example3.nq } LOAD_DIR={MY_DIR} ', 
   network_owner=>'RDFUSER', network_name=>'NET1' );
END;
/

関連項目:

1.12.1 SPARQL更新操作の調整

場合によっては、SPARQL更新操作を調整しなければならないことがあります。SPARQL更新操作では、1つまたは複数のSPARQL問合せがUPDATE文のWHERE句に基づいて実行されるため、SPARQL更新操作には、「問合せパフォーマンスのベスト・プラクティス」もあてはまります。また、次の点にも留意する必要があります。

  • 削除の操作で高いパフォーマンスを得るためには、アプリケーション表に対する適切な索引(SEM_APIS.UPDATE_MODELapply_modelモデルに関連付けられた索引)が必要です。TRIPLEという名前のSDO_RDF_TRIPLE_S列を持つAPP_TABという名前のアプリケーション表を考えた場合、次のような索引が有効です(これは「RDF Semantic Graph Support for Apache Jena」で使用されている索引と同じです)。

    -- Application table index for 
    --  (graph_id, subject_id, predicate_id, canonical_object_id)
    CREATE INDEX app_tab_idx ON app_tab app (
      BITAND(app.triple.rdf_m_id,79228162514264337589248983040)/4294967296,
      app.triple.rdf_s_id,
      app.triple.rdf_p_id,
      app.triple.rdf_c_id)
    COMPRESS;
    
  • パフォーマンスに関係するSEM_MATCHオプションを、SEM_APIS.UPDATE_MODELmatch_optionsパラメータへ渡すことができます。また、PARALLELやDYNAMIC_SAMPLINGのようなパフォーマンスに関係するオプションを、そのプロシージャのoptionsパラメータで指定することができます。次の例では、更新に対し、オプション・パラメータを使用して並列度を4に、またオプティマイザの動的サンプリング・レベルを6に設定しています。さらにこの例では、仮想モデルVM1に対する照合で、ALLOW_DUP=Tが照合オプションとして使用されています。

    BEGIN
      sem_apis.update_model(
       'electronics',
       'PREFIX : <http://www.example.org/electronics/> 
        INSERT { graph :digitalCameras { ?s ?p ?o } }
        WHERE  { ?s :cameraType :digitalCamera .
                 ?s ?p ?o }',
       match_models=>sem_models('VM1'),
       match_models=>sem_models('VM1'),
       match_options=>' ALLOW_DUP=T ',
       options=>' PARALLEL(4) DYNAMIC_SAMPLING(6) ', 
       network_owner=>'RDFUSER', network_name=>'NET1');
    END;
    /
    
  • インライン問合せオプティマイザ・ヒントをWHERE句で指定できます。次の例では、先の例を拡張して、HINT0ヒントをWHERE句で、FINAL_VALUE_NLヒントをmatch_optionsパラメータで使用しています。

    BEGIN
      sem_apis.update_model(
       'electronics',
       'PREFIX : <http://www.example.org/electronics/> 
        INSERT { graph :digitalCameras { ?s ?p ?o } }
        WHERE  { # HINT0={ LEADING(t0 t1) USE_NL(t0 t1)
                 ?s :cameraType :digitalCamera .
                 ?s ?p ?o }',
       match_models=>sem_models('VM1'),
       match_options=>' ALLOW_DUP=T FINAL_VALUE_NL ',
       options=>' PARALLEL(4) DYNAMIC_SAMPLING(6) ', 
       network_owner=>'RDFUSER', network_name=>'NET1');
    END;
    /
    

1.12.2 SPARQL更新操作でのトランザクション管理

SEM_APIS.UPDATE_MODEL操作で使用されるトランザクションの数、およびそれらが自動的にコミットされるのかを、ある程度制御することができます。

デフォルトでは、SEM_APIS.UPDATE_MODELプロシージャは、正常終了後にコミットされたかエラー発生時にロール・バックされた単一のトランザクションで実行されます。たとえば、次に示す呼出しでは、3つの更新操作(セミコロンで分離)が、1つのトランザクションで実行されています。

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX elec: <http://www.example.org/electronics/>
    PREFIX ecom: <http://www.example.org/ecommerce/> 
    # insert camera data
    INSERT DATA {
      elec:camera1 elec:name "Camera 1" .
      elec:camera1 elec:price 120 .
      elec:camera1 elec:cameraType elec:DigitalCamera .
      elec:camera2 elec:name "Camera 2" .
      elec:camera2 elec:price 150 .
      elec:camera2 elec:cameraType elec:DigitalCamera . }; 
    # insert ecom:price triples
    INSERT { ?c  ecom:price ?p }
    WHERE  { ?c  elec:price ?p };
    # delete elec:price triples
    DELETE WHERE { ?c elec:price ?p }', 
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
/

PL/SQL procedure successfully completed.

一方、次の例では、3つのSEM_APIS.UPDATE_MODEL呼出しを別々に実行して、別個のトランザクション3つで、3つの同じ更新操作を実行しています。

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX elec: <http://www.example.org/electronics/>
    PREFIX ecom: <http://www.example.org/ecommerce/> 
    # insert camera data
    INSERT DATA {
      elec:camera1 elec:name "Camera 1" .
      elec:camera1 elec:price 120 .
      elec:camera1 elec:cameraType elec:DigitalCamera .
      elec:camera2 elec:name "Camera 2" .
      elec:camera2 elec:price 150 .
      elec:camera2 elec:cameraType elec:DigitalCamera . }', 
   network_owner=>'RDFUSER', network_name=>'NET1');
END;

PL/SQL procedure successfully completed.

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX elec: <http://www.example.org/electronics/>
    PREFIX ecom: <http://www.example.org/ecommerce/> 
    # insert ecom:price triples
    INSERT { ?c  ecom:price ?p }
    WHERE  { ?c  elec:price ?p }', 
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
/

PL/SQL procedure successfully completed.

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX elec: <http://www.example.org/electronics/>
    PREFIX ecom: <http://www.example.org/ecommerce/> 
    # insert elec:price triples
    DELETE WHERE { ?c elec:price ?p }', 
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
/

PL/SQL procedure successfully completed.

AUTOCOMMIT=Fオプションを使用して、各々のSEM_APIS.UPDATE_MODEL呼出しに、別々のトランザクションが割り当てられるのを防ぐことができます。このオプションでは、トランザクションの管理は、呼出し側の責任です。更新操作を、先の例で3つの分離したトランザクションではなく、単一のトランザクションとして実行する方法を、次の例に示します。

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX elec: <http://www.example.org/electronics/>
    PREFIX ecom: <http://www.example.org/ecommerce/> 
    # insert camera data
    INSERT DATA {
      elec:camera1 elec:name "Camera 1" .
      elec:camera1 elec:price 120 .
      elec:camera1 elec:cameraType elec:DigitalCamera .
      elec:camera2 elec:name "Camera 2" .
      elec:camera2 elec:price 150 .
      elec:camera2 elec:cameraType elec:DigitalCamera . }',
   options=>' AUTOCOMMIT=F ',
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
/

PL/SQL procedure successfully completed.

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX elec: <http://www.example.org/electronics/>
    PREFIX ecom: <http://www.example.org/ecommerce/> 
    # insert ecom:price triples
    INSERT { ?c  ecom:price ?p }
    WHERE  { ?c  elec:price ?p }',
   options=>' AUTOCOMMIT=F ',
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
/

PL/SQL procedure successfully completed.

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX elec: <http://www.example.org/electronics/>
    PREFIX ecom: <http://www.example.org/ecommerce/> 
    # insert elec:price triples
    DELETE WHERE { ?c elec:price ?p }',
   options=>' AUTOCOMMIT=F ',
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
/

PL/SQL procedure successfully completed.

COMMIT;

Commit complete.

ただし、AUTOCOMMIT=Fオプションでは、次のことはできません。

  • バルク操作(FORCE_BULK=TDEL_AS_INS=T)

  • LOAD操作

  • 中間データの実体化(STREAMING=F)

1.12.2.1 トランザクション分離レベル

Oracle Databaseは3つのトランザクション分離レベル(読取りコミット、シリアライズ可能、読取り専用)に対応しています。

読取りコミット分離レベルがデフォルトです。この分離レベルを使用したトランザクションでは、問合せ(そのトランザクションではなく)の開始前にコミットされたデータ、またはトランザクション自体により行われた変更のみが問合せの対象になります。この分離レベルを用いることで、同時実効性を最も高くすることができます。

シリアライズ可能分離レベルを使用したトランザクションでは、問合せの開始前にコミットされたデータ、またはトランザクション自体により行われた変更のみが問合せの対象になります。

読取り専用分離レベルは、シリアライズ可能分離レベルと動作が似ていますが、トランザクションによってデータを修正することはできません。

SEM_APIS.UPDATE_MODELは、読取りコミットおよびシリアル化可能のトランザクション分離レベルに対応しており、読取りコミットがデフォルトです。SPARQL UPDATE操作は、次の基本的ステップに従って処理されます。

  1. 削除するトリプルのセットを取得する問合せが実行されます。

  2. 挿入するトリプルのセットを取得する問合せが実行されます。

  3. ステップ1で取得されたトリプルが削除されます。

  4. ステップ2で取得されたトリプルが挿入されます。

デフォルトの読取りコミット分離レベルでは、同時実行されるトランザクションにより基礎となるトリプル・データに変更が加えられることがあるため、各ステップで異なるデータが対象となる可能性があります。さらに、同時実行されるトランザクションにより加えられる変更は、同じSEM_APIS.UPDATE_MODEL呼び出しで実行されるその後の更新操作の対象となります。なお、中間データの実体化を使用すると(STREAMING=F)、ステップ1とステップ2は1つのステップとして実行されるため、このオプションでは、ステップ1とステップ2の間で、基礎となるトリプル・データに変更を加えることはできません。中間データの実体化に関する詳細は、「バルク操作のサポート」を参照してください。

シリアライズ可能分離レベルは、オプションSERIALIZABLE=Tを指定することで使用できます。その場合、各ステップの対象は、モデルの更新操作が始まる前にコミットされたデータのみであり、他のトランザクションで並行して実行される更新操作により加えられる変更は、1回のSEM_APIS.UPDATE_MODEL呼出しで複数実行される更新操作の対象にはなりません。ただし、SEM_APIS.UPDATE_MODELの実行によって、並行するトランザクションで変更されたトリプルに対し更新が試行されると、ORA-08177エラーが発生します。SERIALIZABLE=Tを使用する場合、ORA-08177エラーがアプリケーションにより検知され、処理される必要があります(たとえば、最初の試行でシリアル化できなかった場合の更新コマンド再試行)。

次の操作を、SERIALIZABLE=Tオプションとともに使用することはできません。

  • バルク操作(FORCE_BULK=TDEL_AS_INS=T)

  • LOAD操作

  • 中間データの実体化(STREAMING=F)

1.12.3 バルク操作のサポート

SEM_APIS.UPDATE_MODELは、大量の更新を効率的に実行するバルク操作に対応しています。次のオプションが利用可能です。ただし、そうしたバルク操作を実行する場合には、シリアル化可能分離(SERIALIZABLE=T)および自動コミットの抑制(AUTOCOMMMIT=F)は使用できません。

1.12.3.1 中間データの実体化(STREAMING=F)(STREAMING=F)

デフォルトでは、SEM_APIS.UPDATE_MODELの実行により、基本的なDELETE INSERT SPARQL更新操作に対し2つの問合せ(削除するトリプルを探す問合せと、挿入するトリプルを探す問合せ)が実行されます。評価に時間のかかるWHERE句を含む更新操作を行う場合、2つの問合せを実行することは最も良いパフォーマンスにつながらないことがあります。そうした場合、WHERE句に対して1回の問合せを実行し、結果を実体化した後、実体化した結果を用いて、削除するトリプルおよび挿入するトリプルの構築を行う方が、より良いパフォーマンスを得られることがあります。この方法ではDDL操作によるオーバーヘッドが生じますが、複雑な更新文の場合には、全体としてパフォーマンスの向上が期待できます。

次に示す更新の例では、このオプション(STREAMING=F)が使用されています。なお、STREAMING=Fは、シリアル化可能分離(SERIALIZABLE=T)あるいは自動コミット抑制(AUTOCOMMIT=F)と同時には使用できません。

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/> 
    DELETE { ?s ?p ?o } 
    INSERT { graph :digitalCameras { ?s ?p ?o } }
    WHERE  { ?s :cameraType :digitalCamera .
             ?s ?p ?o }',
  options=>' STREAMING=F ', 
  network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
1.12.3.2 SEM_APIS.BULK_LOAD_FROM_STAGING_TABLEの使用

大量のトリプル(万単位のような)を挿入する更新の場合、アプリケーション表に対する増分DMLというデフォルトの方法では、十分なパフォーマンスを得られないことがあります。そのような場合、FORCE_BULK=Tオプションを指定して、増分DMLではなくSEM_APIS.BULK_LOAD_FROM_STAGING_TABLEが使用されるようにすることができます。

ただし、すべての更新操作でこの最適化を使用できるわけではありません。FORCE_BULK=Tオプションは、単一のADD操作または単一のINSERT WHERE操作を含むSEM_APIS.UPDATE_MODEL呼出しに対してのみ使用可能です。SEM_APIS.BULK_LOAD_FROM_STAGING_TABLEにより、一連のコミットおよび自律的なトランザクションが発生するため、AUTOCOMMIT=FおよびSERIALIZABLE=Tオプションは、FORCE_BULK=Tと同時に使用できません。さらに、バルク・ロードはCLOB_UPDATE_SUPPORT=Tと同時に使用できません。

SEM_APIS.BULK_LOAD_FROM_STAGING_TABLEは、その中のflagsパラメータを用いて、様々にカスタマイズできます。SEM_APIS.UPDATE_MODELは、BULK_OPTIONS={ OPTIONS_STRING }フラグに対応しているため、OPTIONS_STRINGSEM_APIS.BULK_LOAD_FROM_STAGING_TABLEflagsインプットに渡して、バルク・ロードのオプションをカスタマイズできます。次の例に、FORCE_BULK=Tオプション、およびBULK_OPTIONSフラグを使用したSEM_APIS.UPDATE_MODELの呼出しを示します。

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX elec: <http://www.example.org/electronics/>
    PREFIX ecom: <http://www.example.org/ecommerce/> 
    INSERT { ?c  ecom:price ?p }
    WHERE  { ?c  elec:price ?p }',
   options=>' FORCE_BULK=T BULK_OPTIONS={  parallel=4 parallel_create_index }', 
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
1.12.3.3 挿入としての削除の使用(DEL_AS_INS=T)

大量のトリプル(何万もの)を削除する更新の場合、アプリケーション表に対する増分DMLというデフォルトの方法では、十分なパフォーマンスを得られないことがあります。その場合、DEL_AS_INS=Tを指定できます。このオプションを使用すると、大規模な削除の操作が、INSERT、TRUNCATE、そしてEXCHANGE PARTITIONの操作として実行されます。

DEL_AS_INS=Tを使用すると一連のコミットおよび自律的なトランザクションが発生するため、このオプションは、SERIALIZABLE=Tまたは AUTOCOMMIT=Fと同時に使用できません。さらに、このオプションは、単一のDELETE WHERE操作、単一のDROP操作、あるいは単一のCLEAR操作が含まれたSEM_APIS.UPDATE_MODEL呼出しと組合わせた場合にのみ使用することができます。

挿入としての削除では、中間操作でSEM_APIS.MERGE_MODELSが内部的に使用されています。OPTIONS_STRINGの文字列を、MM_OPTIONS={ OPTIONS_STRING }フラグから指定して、マージのオプションをカスタマイズすることができます。次の例で、DEL_AS_INS=TオプションおよびMM_OPTIONSフラグを使用したSEM_APIS.UPDATE_MODELの呼出しを示します。

BEGIN
  sem_apis.update_model('electronics',
   'CLEAR NAMED',
   options=>' DEL_AS_INS=T MM_OPTIONS={  dop=4 } ', 
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
/

1.12.4 セッション・レベルでのUPDATE_MODELオプションの設定

SEM_APIS.UPDATE_MODELプロシージャの動作に影響を与える設定の中には、特殊なMDSYS.SDO_SEM_UPDATE_CTX.SET_PARAMプロシージャを使用して、セッション・レベルで修正できるものがあります。autocommitstreamingstrict_bnodeおよびclob_supportの各オプションは、セッション・レベルでtrueまたはfalseに設定できます。

MDSYS.SDO_SEM_UPDATE_CTXには、SEM_APIS.UPDATE_MODELパラメータをセッション・レベルで取得し、設定する次のサブプログラムが含まれています。

SQL> describe mdsys.sdo_sem_update_ctx
FUNCTION GET_PARAM RETURNS VARCHAR2
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 NAME                           VARCHAR2                IN
PROCEDURE SET_PARAM
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 NAME                           VARCHAR2                IN
 VALUE                          VARCHAR2                IN

次の例では、AUTOCOMMIT=Fを使用するSEM_APIS.UPDATE_MODELプロシージャに対するすべての呼出しをこの後、セッションの終わりまで、あるいは異なるautocommit値を指定する次のSEM_APIS.UPDATE_MODEL呼出しまで、発生させています。

begin
  mdsys.sdo_sem_update_ctx.set_param('autocommit','false');
end;
/

1.12.5 ロード操作: SPARQL更新で特に留意する点

ロードするファイルの形式は、ロード・プロセス中に使用できる並列度に影響します。ロード操作には、次の2つのフェーズがあります。

  1. ファイル・システムからステージング表へのロード

  2. ステージング表からセマンティク・モデルにロードするためのSEM_APIS.BULK_LOAD_FROM_STAGING_TABLEのコール

フェーズ2では、サポートされているすべてのデータ形式がパラレル実行を使用できますが、フェーズ1でパラレル実行を使用できるのはN-TripleおよびN-Quad形式のみです。さらに、ステージング表にデータが完全にロードされた後で、フェーズ2でのロード操作が中断された場合、optionsパラメータでRESUME_LOAD=Tキーワードを指定しておくことで、ロードを再開できます。

4000バイトより長いオブジェクト値を含むRDFドキュメントのロード操作では、追加の操作が必要な場合があります。TurtleおよびTrigドキュメントのロード操作では、オブジェクト値のサイズにかかわらず、すべてのトリプルおよびクワッドが自動的にロードされます。一方、N-TripleおよびN-Quadドキュメントのロード操作では、長さが4000バイト未満のオブジェクト値を持つトリプルおよびクワッドのみがロードされます。N-TripleおよびN-Quadデータの場合は、オブジェクト値が4000バイトより大きいトリプルおよびクワッドもロードするために、LOAD_CLOB_ONLY=Tオプションを指定して2つ目のロード操作を発行する必要があります。

UNIX名前付きパイプからのロードは、N-TripleおよびN-Quad形式についてのみサポートされます。TurtleおよびTrigファイルは、圧縮されていない物理ファイルである必要があります。

Unicode文字の処理は、ロードするRDFファイルの形式によって異なります。N-TripleおよびN-QuadファイルのUnicode文字は、Unicodeコードポイント値の16進値を使用して、\u<HEX><HEX><HEX><HEX>または\U<HEX><HEX><HEX><HEX><HEX><HEX><HEX><HEX>としてエスケープする必要があります。TurtleおよびTrigファイルにはUnicodeのエスケープは必要なく、エスケープしていないUnicode値を使用して直接ロードできます。

例1-119 N-Quadデータの短いリテラルと長いリテラルのロード

BEGIN
  -- short literal load
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/>
    LOAD <file:///example1.nq>',
   options=> ' LOAD_DIR={MY_DIR} ', 
   network_owner=>'RDFUSER', network_name=>'NET1');

  -- long literal load
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/>
    LOAD <file:///example1.nq>',
   options=> ' LOAD_DIR={MY_DIR} LOAD_CLOB_ONLY=T ',
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
/

1.12.6 ロング・リテラル: SPARQL更新で特に留意する点

デフォルトでは、SPARQL更新で4000バイトよりも長い値が操作されることはありません。ロング・リテラルへの対応を有効にするには、SEM_APIS.UPDATE_MODELプロシージャのオプション・パラメータで、CLOB_UPDATE_SUPPORT=Tを指定します。

ロング・リテラルのバルク・ロードはできません。CLOB_UPDATE_SUPPORT=Tオプションが同時に指定されている場合には、FORCE_BULK=Tオプションは無視されます。

1.12.7 空白のノード: SPARQL更新で特に留意する点

更新操作の中には、1セットのRDFトリプルからなるグラフに影響を与えるだけのものがあります。具体的には、ADD、COPYおよびMOVEといった操作です。たとえば、「セマンティク・モデルでのSPARQL更新操作のサポート」で示されているMOVE操作の例では、:digitalCamerasをグラフとして持つトリプルの更新を行うことができるだけです。ただし、そうした操作のパフォーマンスは、IDに限定した操作をRDFモデルに対して行うことで向上します。大規模なADD、COPYまたはMOVE操作をID限定操作として実行するために、SEM_APIS.UPDATE_MODELプロシージャのoptionsパラメータで、STRICT_BNODE=Fヒントを指定できます。

しかし、ID限定操作の結果、正しくない空白ノードが生ずることがあります。これは、2つのグラフで同じ空白ノードが共有されることがないためです。RDFセマンティク・グラフでは、空白ノードを含むモデルとグラフの組合せに基づく空白ノード接頭辞スキームが使用されています。この接頭辞によって、モデルおよびグラフ全体におけるノード識別子の一意性が保証されています。ADD、COPYおよびUPDATE操作をID限定で行うという方法では、空白ノード接頭辞が更新されません。

例1-120 ID限定更新による誤った空白ノード値の発生

次の例に示す更新では、グラフ:camerasおよび:cameras2のトリプル両方に対して、同じ空白ノードの主語が生じます。このことは、ここで示されているSEM_MATCH問合せを実行することで確かめられます。

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/> 
    INSERT DATA { 
       GRAPH :cameras { :camera2 :owner _:bn1 .
                        _:bn1 :name "Axel" }
    };
    COPY :cameras TO :cameras2',
   options=>' STRICT_BNODE=F ', 
   network_owner=>'RDFUSER', network_name=>'NET1');
END;
/

SELECT count(s)
FROM TABLE( SEM_MATCH('
  PREFIX : <http://www.example.org/electronics/> 
  SELECT * 
  WHERE { { graph :cameras  {?s :name "Axel"  } }
          { graph :cameras2 {?s :name "Axel"  } } }
', sem_models('electronics'),null,null,null,null,' STRICT_DEFAULT=T ',
null, null, 'RDFUSER', 'NET1'));

ADD、COPYまたはMOVE更新操作の対象に空白ノードが含まれていないことがわかっている場合、そのようなエラーを防ぐには、SEM_APIS.UPDATE_MODELプロシージャのoptionsパラメータで、STRICT_BNODE=Fヒントを指定します。

ただし、大規模なグラフに対するADD、COPYおよびMOVEの操作では、デフォルトの方法よりも、STRICT_BNODE=Fオプションを用いた方が、実行速度が大幅に早くなります。ID限定の更新を行う必要がある場合、もう1つの方法は、STRICT_BNODE=Fオプションを使用してから、最後にSEM_APIS.CLEANUP_BNODESプロシージャを実行することです。この方法では、与えられたモデルの空白ノードすべての接頭辞がリセットされ、誤った空白ノードのラベルすべてが効果的に修正(「クリーン・アップ」)されます。

なお、ADD、COPYまたはMOVE操作の回数が少ない場合には、この2段階からなる方法は用いないでください。少数の操作をデフォルトの方法を用いて実行する方が、少数のID限定操作を実行してからSEM_APIS.CLEANUP_BNODESプロシージャを実行するよりも高速です。

次の例では、electronicsという名前のセマンティク・モデルの空白ノードを修正しています。

EXECUTE sem_apis.cleanup_bnodes('electronics');

1.13 RDFによるOracle Database In-Memoryのサポート

RDFでは、インメモリー列ストアなどの、Oracle Database In-Memoryの一連のインメモリー機能を使用して、リアルタイム分析および混合ワークロードのパフォーマンスを向上できます。

Database In-Memoryを設定したら、SEM_APIS.ENABLE_INMEMORYプロシージャを使用してRDFのインメモリー・ロードを実行できます。これには管理権限が必要で、セマンティク・ネットワークに影響します。これにより、頻繁に使用される列がRDF_LINK$表およびRDF_VALUE$表からメモリーにロードされます。

このプロシージャの実行後、RDFインメモリー仮想列をメモリーにロードできます。これは仮想モデル・レベルで実行されます。RDF仮想モデルの作成時に、SEM_APIS.CREATE_VIRTUAL_MODELへのコールでインメモリー・オプションを指定できます。

SEM_APIS.ENABLE_INMEMORY_FOR_MODELSEM_APIS.ENABLE_INMEMORY_FOR_ENTSEM_APIS.DISABLE_INMEMORY_FOR_MODELおよびSEM_APIS.DISABLE_INMEMORY_FOR_ENTプロシージャを使用して、指定されたモデルおよび伴意(ルール索引)のRDFデータのインメモリー移入を有効化および無効化することもできます。

ノート:

Oracle Database In-MemoryでRDFを使用するには、『Oracle Database In-Memoryガイド』で説明されている、Oracle Database In-Memoryの有効化および構成方法を理解している必要があります。

1.13.1 RDFのOracle Database In-Memoryの有効化

RDFデータをメモリーにロードするには、compatibilityを12.2以降に設定し、inmemory_size値を100MB以上に設定する必要があります。これにより、SEM_APIS.ENABLE_INMEMORYプロシージャを使用してセマンティク・ネットワークをメモリーにロードできるようになります。

メモリー内でRDFデータを使用する前に、データがメモリーにロードされていることを確認する必要があります。

SQL> select pool, alloc_bytes, used_bytes, populate_status from V$INMEMORY_AREA;
POOL			   ALLOC_BYTES USED_BYTES POPULATE_STATUS
-------------------------- ----------- ---------- --------------------------
1MB POOL		    5.0418E+10 4.4603E+10 DONE
64KB POOL		    3202088960	  9568256  DONE 

POPULATE_STATUS値がDONEの場合、RDFデータはメモリーに完全にロードされています。

メモリー内のRDFデータが使用されているどうかを確認するには、実行計画でTABLE ACCESS INMEMORY FULLを検索します。

--------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation			  | Name      | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |    TQ  |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT		  |	      |     1 |    13 |   580  (60)| 00:00:01 |       |       |        |      | 	   |
|   1 |  VIEW				  |	      |     1 |    13 |   580  (60)| 00:00:01 |       |       |        |      | 	   |
|   2 |   VIEW				  |	      |     1 |    13 |   580  (60)| 00:00:01 |       |       |        |      | 	   |
|   3 |    SORT AGGREGATE		  |	      |     1 |    16 | 	   |	      |       |       |        |      | 	   |
|   4 |     PX COORDINATOR		  |	      |       |       | 	   |	      |       |       |        |      | 	   |
|   5 |      PX SEND QC (RANDOM)	  | :TQ10000  |     1 |    16 | 	   |	      |       |       |  Q1,00 | P->S | QC (RAND)  |
|   6 |       SORT AGGREGATE		  |	      |     1 |    16 | 	   |	      |       |       |  Q1,00 | PCWP | 	   |
|   7 |        PX BLOCK ITERATOR	  |	      |   242M|  3697M|   580  (60)| 00:00:01 |KEY(I) |KEY(I) |  Q1,00 | PCWC | 	   |
|   8 | 	TABLE ACCESS INMEMORY FULL| RDF_LINK$ |   242M|  3697M|   580  (60)| 00:00:01 |KEY(I) |KEY(I) |  Q1,00 | PCWP | 	   |
--------------------------------------------------------------------------------------------------------------------------------------------

RDFデータのインメモリー移入を無効にするには、SEM_APIS.DISABLE_INMEMORYプロシージャを使用します。

1.13.2 RDFでのインメモリー仮想列の使用

メモリー内のRDFデータに加え、RDFインメモリー仮想列を使用してRDF_LINK$表内のRDF語句の字句の値をメモリーにロードできます。RDFインメモリー仮想列をロードするには、まず、inmemory_virtual_columnsパラメータをENABLEに設定し、管理権限を使用してSEM_APIS.ENABLE_INMEMORYを実行する必要があります。インメモリー仮想列がRDF_LINK$表に作成され、仮想モデル・レベルでメモリーにロードされます。

仮想列をメモリーにロードするには、SEM_APIS.CREATE_VIRTUAL_MODELへのコールで'PXN=F INMEMORY=T'オプションを使用します。たとえば(RDFUSERという名前のデータベース・ユーザーが所有するNET1という名前のスキーマプライベート・ネットワークがあると仮定した場合):

EXECUTE  SEM_APIS.CREATE_VIRTUAL_MODEL ('vm2',SEM_MODELS('lubm1k','univbench'),SEM_RULEBASES ('owl2rl'),options=>'PXN=F INMEMORY=T', network_owner=>'RDFUSER', network_name=>'NET1');

MDSYS.RDF_MODEL$ビューを調べることで、インメモリー仮想モデルを確認できます。インメモリー仮想モデルの場合は、INMEMORY列がTに設定されています。

インメモリー仮想モデルを使用すると、RDF_VALUE$表との結合が不要になります。インメモリー仮想モデルの使用方法を確認するには、「RDFのOracle Database In-Memoryの有効化」で示したものと同じコマンドを使用します。

移入されていない仮想列は実行時にアセンブルされ、このオーバーヘッドがパフォーマンスを損なう可能性があるため、最高のパフォーマンスを実現するには、問合せを処理する前にインメモリー仮想列を完全に移入してください。

1.13.3 Oracle Database In-Memoryでの不可視索引の使用

索引の使用によって、問合せのパフォーマンスの一貫性が損なわれる場合があります。異なるワークロード間で一貫したパフォーマンスが得られるようにするには、RDFセマンティク・ネットワーク索引を不可視にして、問合せ実行がメモリーのスキャンによってのみ行われるようにします。ただしこの場合、索引を使用することで通常得られるパフォーマンスの向上が打ち消されます。次の例では、RDFUSERという名前のデータベース・ユーザーが所有する、NET1という名前のスキーマプライベート・ネットワークで、RDFセマンティク・ネットワーク索引を非表示にします。

EXECUTE SEM_APIS.ALTER_SEM_INDEXES('VISIBILITY','N', network_owner=>'RDFUSER', network_name=>'NET1');

RDFセマンティク・ネットワーク索引を再度可視にするには、次を使用します

EXECUTE SEM_APIS.ALTER_SEM_INDEXES('VISIBILITY','Y', network_owner=>'RDFUSER', network_name=>'NET1');

ノート:

RDF_VALUE$索引は、Oracle Databaseがコンパイル時に問合せ定数に対してVALUE_IDを効率的に参照できるように可視である必要があります。

不可視索引および使用不可の索引の詳細は、『Oracle Database管理者ガイド』を参照してください。

1.14 Oracle SQL DeveloperでのRDFのサポート

Oracle SQL Developerを使用して、Oracle Spatial and GraphのRDFナレッジ・グラフ機能に関連する操作を実行できます。

詳細は、「SQL DeveloperでのRDFのサポート」を参照してください。

1.15 強化されたRDF ORDER BY問合せ処理

Oracle Databaseリリース12.2では、SPARQL ORDER BYセマンティクを使用するRDFデータの処理効率が、以前のリリースに比べて向上しています。

この内部処理の効率向上には、RDF_VALUE$メタデータ表(「文」を参照)のORDER_TYPE列、ORDER_NUM列およびORDER_DATE列が関与しています。この3つの列に対する値はロード中に格納されるため、ORDER BY問合せでの内部関数呼出しの低減と、実行時間の短縮が可能になります。

Oracle Databaseリリース12.2では、プロシージャSEM_APIS.ADD_DATATYPE_INDEXにより、以前のバージョンのように関数ベースの索引が作成されるのではなく、数値型(xsd:float、xsd:doubleおよびxsd:decimalとそのサブタイプ)のORDER_NUM列に対する索引と、日付に関連する型(xsd:date、xsd:timeおよびxsd:dateTime)のORDER_DATE列に対する索引が作成されます。これらのデータ型に対して引続き関数ベースの索引を使用する場合には、SEM_APIS.ADD_DATATYPE_INDEXプロシージャのFUNCTION=Tオプションを使用する必要があります。たとえば(RDFUSERという名前のデータベース・ユーザーが所有するNET1という名前のスキーマプライベート・セマンティク・ネットワークがあると仮定した場合):

EXECUTE sem_apis.add_datatype_index('http://www.w3.org/2001/XMLSchema#decimal', options=>'FUNCTION=T', network_owner=>'RDFUSER', network_name=>'NET1');

EXECUTE sem_apis.add_datatype_index('http://www.w3.org/2001/XMLSchema#date', options=>'FUNCTION=T', network_owner=>'RDFUSER', network_name=>'NET1');

1.16 セマンティク・データの例(PL/SQLおよびJava)

このトピックではPL/SQLの例が示されています。

Javaの例は、「RDF Semantic Graph Support for Apache Jena」を参照してください。

1.16.1 例: 雑誌記事の情報

この項では、雑誌記事に関する文のモデルに対応する簡単なPL/SQLの例を示します。例1-121では、説明のためのコメントとともに、この章で説明されている各概念が参照され、「SEM_APISパッケージ・サブプログラム」で述べられている関数とプロシージャが使用されています。

例1-121 雑誌記事の情報に関するモデルの使用

-- Basic steps:
-- After you have connected as a privileged user and called 
-- SEM_APIS.CREATE_SEM_NETWORK to create a schema for storing RDF data,
-- connect as a regular database user and do the following.

-- 1. For each desired network, create a model (SEM_APIS.CREATE_SEM_MODEL). 
-- Note that we are using the schema-private network NET1 created in 
-- "Quick Start for Using Semantic Data".

EXECUTE SEM_APIS.CREATE_SEM_MODEL('articles', 'null', 'null', network_owner=>'RDFUSER', network_name=>'NET1');
 
-- Information to be stored about some fictitious articles:
-- Article1, titled "All about XYZ" and written by Jane Smith, refers 
--   to Article2 and Article3.
-- Article2, titled "A review of ABC" and written by Joe Bloggs, 
--   refers to Article3.
-- Seven SQL statements to store the information. In each statement:
-- Each article is referred to by its complete URI The URIs in
--   this example are fictitious.
-- Each property is referred to by the URL for its definition, as 
--   created by the Dublin Core Metadata Initiative.
 
-- 2. Use SEM_APIS.UPDATE_MODEL to insert data with SPARQL Update statements
 
BEGIN
  SEM_APIS.UPDATE_MODEL('articles',
   'PREFIX  nature: <http://nature.example.com/>
    PREFIX      dc: <http://purl.org/dc/elements/1.1/>
    PREFIX dcterms: <http://purl.org/dc/terms/>

    INSERT DATA {

      # article1 has the title "All about XYZ".
      # article1 was created (written) by Jane Smith.
      # article1 references (refers to) article2 and article3
      nature:article1 dc:title "All about XYZ" ;
                      dc:creator "Jane Smith" ;
                      dcterms:references nature:article2, 
                                         nature:article3 . 

      # article2 has the title "A review of ABC".
      # article2 was created (written) by Joe Bloggs.
      # article2 references (refers to) article3.                    
      nature:article2 dc:title "A Review of ABC" ;
                      dc:creator "Joe Bloggs" ;
                      dcterms:references nature:article3 .
    }',
   network_owner=>'RDFUSER',
   network_name=>'NET1');   
END;
/

-- 3. Query semantic data with SEM_MATCH table function.
-- 3.a Get all article authors and titles
SELECT author$rdfterm, title$rdfterm
FROM TABLE(SEM_MATCH(
'PREFIX dc: <http://purl.org/dc/elements/1.1/>
 SELECT ?author ?title
 WHERE { ?article dc:creator ?author
                ; dc:title  ?title . }'
, SEM_MODELS('articles')
, null, null, null, null
, ' PLUS_RDFT=VC '
, null, null
, 'RDFUSER', 'NET1'));

-- 3.b Find all articles referenced by Article1
SELECT ref$rdfterm
FROM TABLE(SEM_MATCH(
'PREFIX dcterms: <http://purl.org/dc/terms/>
 PREFIX  nature: <http://nature.example.com/>
 SELECT ?ref
 WHERE { nature:article1 dcterms:references ?ref . }'
, SEM_MODELS('articles')
, null, null, null, null
, ' PLUS_RDFT=VC '
, null, null
, 'RDFUSER', 'NET1'));

1.16.2 例: 家系の情報

この項では、ファミリ・ツリー(家系)情報に関する文のモデルに対応する簡単なPL/SQLの例を示します。例1-121では、説明のためのコメントとともに、この章で説明されている各概念が参照され、「SEM_APISパッケージ・サブプログラム」で述べられている関数とプロシージャが使用されています。

この例の家族関係は、図1-3のファミリ・ツリーを反映しています。また、この図では、例における一部の情報(CathyはJackの姉妹、JackとTomは男性、Cindyは女性)が直接言明されています。

図1-3 RDFの例のファミリ・ツリー

図1-3の説明が続きます
「図1-3 RDFの例のファミリ・ツリー」の説明

例1-122 家系の情報に関するモデルの使用

-- Preparation: create tablespace; enable RDF support.
-- Connect as a privileged user. Example: CONNECT SYSTEM/password-for-SYSTEM
-- Create a tablespace for the RDF data. Example:
CREATE TABLESPACE rdf_tblspace 
  DATAFILE 'rdf_tblspace.dat' 
    SIZE 128M REUSE
    AUTOEXTEND ON NEXT 128M MAXSIZE 4G
  SEGMENT SPACE MANAGEMENT AUTO;

-- Call SEM_APIS.CREATE_SEM_NETWORK to create a schema-private semantic
-- network named NET1 owned by RDFUSER, which will create database
-- objects to store RDF data. Example:
EXECUTE SEM_APIS.CREATE_SEM_NETWORK('rdf_tblspace', network_owner=>'RDFUSER', network_name=>'NET1');

-- Connect as the user that is to perform the RDF operations (not SYSTEM), 
-- and do the following:
-- 1. For each desired model, create an application table
-- 2. For each desired model, create a model (SEM_APIS.CREATE_SEM_MODEL).
-- 3. Use various subprograms and constructors.


-- Create the application table for the model.
CREATE TABLE family_rdf_data (triple SDO_RDF_TRIPLE_S) COMPRESS;
 
-- Create the model.
execute SEM_APIS.create_sem_model('family', 'family_rdf_data', 'triple', network_owner=>'RDFUSER', network_name=>'NET1');
 
-- Insert RDF triples using SEM_APIS.UPDATE_MODEL. These express the following information:
-----------------
-- John and Janice have two children, Suzie and Matt.
-- Matt married Martha, and they have two children:
--   Tom (male) and Cindy (female).
-- Suzie married Sammy, and they have two children:
--   Cathy (female) and Jack (male).
 
-- Person is a class that has two subslasses: Male and Female.
-- parentOf is a property that has two subproperties: fatherOf and motherOf.
-- siblingOf is a property that has two subproperties: brotherOf and sisterOf.
-- The domain of the fatherOf and brotherOf properties is Male.
-- The domain of the motherOf and sisterOf properties is Female.
------------------------
 
BEGIN

  -- Insert some TBox (schema) information.
  SEM_APIS.UPDATE_MODEL('family',
   'PREFIX    rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
    PREFIX   rdfs: <http://www.w3.org/2000/01/rdf-schema#>
    PREFIX family: <http://www.example.org/family/>

    INSERT DATA {

      # Person is a class.
      family:Person rdf:type rdfs:Class .

      # Male is a subclass of Person.
      family:Male rdfs:subClassOf family:Person .
 
      # Female is a subclass of Person. 
      family:Female rdfs:subClassOf family:Person .

      # siblingOf is a property.
      family:siblingOf rdf:type rdf:Property .
 
      # parentOf is a property.
      family:parentOf rdf:type rdf:Property .
 
      # brotherOf is a subproperty of siblingOf.
      family:brotherOf rdfs:subPropertyOf family:siblingOf .

      # sisterOf is a subproperty of siblingOf.
      family:sisterOf rdfs:subPropertyOf family:siblingOf .
 
      # A brother is male.
      family:brotherOf rdfs:domain family:Male .
 
      # A sister is female.
      family:sisterOf rdfs:domain family:Female .

      # fatherOf is a subproperty of parentOf.
      family:fatherOf rdfs:subPropertyOf family:parentOf .
 
      # motherOf is a subproperty of parentOf.
      family:motherOf rdfs:subPropertyOf family:parentOf .

      # A father is male.
      family:fatherOf rdfs:domain family:Male .
 
      # A mother is female.
      family:motherOf rdfs:domain family:Female .
    }',
   network_owner=>'RDFUSER',
   network_name=>'NET1');

  -- Insert some ABox (instance) information.
  SEM_APIS.UPDATE_MODEL('family',
   'PREFIX    rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
    PREFIX   rdfs: <http://www.w3.org/2000/01/rdf-schema#>
    PREFIX family: <http://www.example.org/family/>

    INSERT DATA {
      # John is the father of Suzie and Matt
      family:John family:fatherOf family:Suzie .
      family:John family:fatherOf family:Matt .

      # Janice is the mother of Suzie and Matt
      family:Janice family:motherOf family:Suzie .
      family:Janice family:motherOf family:Matt .

      # Sammy is the father of Cathy and Jack
      family:Sammy family:fatherOf family:Cathy .
      family:Sammy family:fatherOf family:Jack .

      # Suzie is the mother of Cathy and Jack
      family:Suzie family:motherOf family:Cathy .
      family:Suzie family:motherOf family:Jack .

      # Matt is the father of Tom and Cindy
      family:Matt family:fatherOf family:Tom .
      family:Matt family:fatherOf family:Cindy .

      # Martha is the mother of Tom and Cindy
      family:Martha family:motherOf family:Tom .
      family:Martha family:motherOf family:Cindy .

      # Cathy is the sister of Jack
      family:Cathy family:sisterOf family:Jack .

      # Jack is male
      family:Jack rdf:type family:Male .

      # Tom is male.
      family:Tom rdf:type family:Male .

      # Cindy is female.
      family:Cindy rdf:type family:Female .
    }',
   network_owner=>'RDFUSER',
   network_name=>'NET1');

END;
/


-- RDFS inferencing in the family model
BEGIN
  SEM_APIS.CREATE_ENTAILMENT(
    'rdfs_rix_family',
    SEM_Models('family'),
    SEM_Rulebases('RDFS'),
    network_owner=>'RDFUSER',
    network_name=>'NET1');
END;
/
 
-- Select all males from the family model, without inferencing.
-- (Returns only Jack and Tom.)
SELECT m$rdfterm
  FROM TABLE(SEM_MATCH(
    'PREFIX  rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
     PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
     PREFIX     : <http://www.example.org/family/>
     SELECT ?m
     WHERE {?m rdf:type :Male}',
    SEM_Models('family'),
    null,  null,  null, null,
    ' PLUS_RDFT=VC ',
    null, null,
    'RDFUSER', 'NET1'));
 
-- Select all males from the family model, with RDFS inferencing.
-- (Returns Jack, Tom, John, Sammy, and Matt.)
SELECT m$rdfterm
  FROM TABLE(SEM_MATCH(
    'PREFIX  rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
     PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
     PREFIX     : <http://www.example.org/family/>
     SELECT ?m
     WHERE {?m rdf:type :Male}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS'), 
    null, null, null,
    ' PLUS_RDFT=VC ',
    null, null,
    'RDFUSER', 'NET1'));
 
-- General inferencing in the family model
 
EXECUTE SEM_APIS.CREATE_RULEBASE('family_rb', network_owner=>'RDFUSER', network_name=>'NET1');
 
INSERT INTO rdfuser.net1#semr_family_rb VALUES(
  'grandparent_rule',
  '(?x :parentOf ?y) (?y :parentOf ?z)',
  NULL,
  '(?x :grandParentOf ?z)', 
  SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')));
 
COMMIT;
 
-- Because a new rulebase has been created, and it will be used in the
-- entailment, drop the preceding entailment and then re-create it.
EXECUTE SEM_APIS.DROP_ENTAILMENT ('rdfs_rix_family', network_owner=>'RDFUSER', network_name=>'NET1');
 
-- Re-create the entailment.
BEGIN
  SEM_APIS.CREATE_ENTAILMENT(
    'rdfs_rix_family',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    network_owner=>'RDFUSER', network_name=>'NET1');
END;
/
 
-- Select all grandfathers and their grandchildren from the family model, 
-- without inferencing. (With no inferencing, no results are returned.)
SELECT x$rdfterm grandfather, y$rdfterm grandchild
  FROM TABLE(SEM_MATCH(
    'PREFIX  rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
     PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
     PREFIX     : <http://www.example.org/family/>
     SELECT ?x ?y
     WHERE {?x :grandParentOf ?y . ?x rdf:type :Male}',
    SEM_Models('family'),
    null, null,  null, null,
    ' PLUS_RDFT=VC ',
    null, null,
    'RDFUSER', 'NET1'));
 
-- Select all grandfathers and their grandchildren from the family model.
-- Use inferencing from both the RDFS and family_rb rulebases.
SELECT x$rdfterm grandfather, y$rdfterm grandchild
  FROM TABLE(SEM_MATCH(
    'PREFIX  rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
     PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
     PREFIX     : <http://www.example.org/family/>
     SELECT ?x ?y
     WHERE {?x :grandParentOf ?y . ?x rdf:type :Male}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null,  null, null,
    ' PLUS_RDFT=VC ',
    null, null,
    'RDFUSER', 'NET1'));

1.17 リリース11.1以上でのソフトウェアの名前の変更

Oracle Databaseリリース11.1では、セマンティク・データのサポートが元のRDFの対象範囲を超えて拡張されているため、多くのソフトウェア・オブジェクト(PL/SQLパッケージ、関数およびプロシージャ、システム表およびビューなど)の名前が変更されています。

ほとんどの場合、この変更で文字列RDFSEMに置換されていますが、SDO_RDFSEMに置換されている場合もあります。

リリース11.1より前の名前を使用しているすべての有効なコードは、引き続き動作します。既存のアプリケーションに障害は発生しません。ただし、古いアプリケーションは変更して新しいオブジェクト名を使用することをお薦めします。新規アプリケーションでは新しい名前を使用してください。このマニュアルでは、新しい名前のみを記載しています。

表1-27に、セマンティク・テクノロジのサポートに関連する一部のオブジェクトの旧名と新規名を、旧名のアルファベット順に示します。

表1-27 セマンティク・テクノロジのソフトウェア・オブジェクト: 旧名と新規名

旧名称 新名称

RDF_ALIASデータ型

SEM_ALIAS

RDF_MODEL$ビュー

SEM_MODEL$

RDF_RULEBASE_INFOビュー

SEM_RULEBASE_INFO

RDF_RULES_INDEX_DATASETSビュー

SEM_RULES_INDEX_DATASETS

RDF_RULES_INDEX_INFOビュー

SEM_RULES_INDEX_INFO

RDFI_rules-index-nameビュー

SEMI_rules-index-name

RDFM_model-nameビュー

SEMM_model-name

RDFR_rulebase-nameビュー

SEMR_rulebase-name

SDO_RDFパッケージ

SEM_APIS

SDO_RDF_INFERENCEパッケージ

SEM_APIS

SDO_RDF_MATCH表関数

SEM_MATCH

SDO_RDF_MODELSデータ型

SEM_MODELS

SDO_RDF_RULEBASESデータ型

SEM_RULEBASES

1.18 RDFセマンティク・グラフの詳細

RDFセマンティク・グラフ・サポートの詳細が用意されています。

次の資料も参照してください。

1.19 リリース12.2よりも前のセマンティク・データに必要な移行作業

Oracle Database 11.1、11.2または12.1で作成されたセマンティク・データがある場合、そのデータをOracle Database 12.2の環境で使用するには、データの移行が必要です。

移行を行うには、SEM_APIS.MIGRATE_DATA_TO_CURRENTプロシージャを使用します。このプロシージャは、既存のセマンティク・データに適用されるだけでなく、環境に導入されているその他のあらゆるセマンティク・データに対しても、そのデータがOracle Database 11.1、11.2または12.1で作成されている場合、適用されます。

こうする必要があるのは、ORDER BYを使用する問合せのパフォーマンスを最適なものにするためです。リリース12.2では、Oracle Databaseによって、RDF_VALUE$表(「文」を参照)のORDER_TYPE列、ORDER_NUM列およびORDER_DATE列(リリース12.2で追加)が作成され、値が格納され、使用されます。SEM_APIS.MIGRATE_DATA_TO_CURRENTプロシージャにより、こうした並べ替えに関連する列に値が格納されます。これが実行されない場合、既存のデータに対してこうした列の値はNULLになります。

このプロシージャを、Oracle Databaseリリース12.2へアップグレードした後に実行します。以前のリリースを使用して作成したセマンティク・データを、リリース12.2の環境へ後から取り込む場合にも、データの使用前にこのプロシージャを実行する必要があります。セマンティク・データの量が多い場合、プロシージャの実行に長時間を要することがあるため、実行のタイミングを決める際にはその点を考慮する必要があります。(なお、大規模なデータ・セットでは、INS_AS_SEL=Tオプションを使用することで、SEM_APIS.MIGRATE_DATA_TO_CURRENTプロシージャのパフォーマンスが向上します。)

1.20 アクセシビリティをサポートするOracle RDF Graphの機能

この項では、Oracle RDF Graphの機能により提供されるアクセシビリティのサポートについて説明します。

  • Oracle Adapter for Eclipse RDF4Jを使用すると、開発者はEclipse RDF4Jフレームワークを使用してOracle DatabaseのRDFグラフ機能と対話できるアプリケーションを構築できます。WCAG 2.1アクセシビリティ標準に基づいてアプリケーションを作成するには、WCAGドキュメントを参照してください。
  • RDF問合せUIは、Oracle JETに基づいています。Oracle JETコンポーネントのアクセシビリティの詳細は、Oracle JETのドキュメントを参照してください。
  • また、RDF問合せUIでアクセシビリティを有効にすると、すべてのSPARQL問合せの実行結果が表形式で表示されます。詳細は、アクセシビリティの項を参照してください。