索引を使用した照会の最適化

索引を適切に定義および使用すると、照会のパフォーマンスをかなり改善できます。

WebSphere® eXtreme Scale 照会では、組み込み HashIndex プラグインを使用すると、照会のパフォーマンスを改善できます。 索引は、エンティティーまたはオブジェクト属性に対して定義できます。照会エンジンは、その WHERE 文節で以下のいずれかのストリングが使用されると、定義された索引を自動的に使用します。

  • 以下の演算子を使用する比較式: =、<、>、<=、または >= (等しくない <> を除くすべての比較式)
  • BETWEEN 式
  • 式のオペランドが定数またはシンプル・ターム

要件

照会で使用される場合、索引には以下の 要件があります。
  • すべての索引は組み込み HashIndex プラグインを使用する必要があります。
  • すべての索引は静的に定義されていなければなりません。動的索引はサポートされません。
  • 自動的に静的 HashIndex プラグインを作成するために @Index アノテーションを 使用できます。
  • すべての単一属性索引の RangeIndex プロパティーは true に設定されていなければなりません。
  • すべての複合索引の RangeIndex プロパティーは false に設定されていなければなりません。
  • すべてのアソシエーション (リレーションシップ) 索引の RangeIndex プロパティーは false に設定されていなければなりません。

HashIndex の構成について詳しくは、データの索引付けのためのプラグインを参照してください。

索引付けについては、索引付けを参照してください。

キャッシュされたオブジェクトを検索するためのより効果的な方法については、複合索引の使用を参照してください。

索引選択に関するヒントの使用

索引は、HINT_USEINDEX 定数付きの setHint メソッドを Query および ObjectQuery インターフェースで使用すると、手動で選択することができます。これは、最も効率的な索引を使用 するよう照会を最適化する際に役立ちます。

属性索引を使用する照会例

以下の例では、シンプル・ターム e.empid、e.name、e.salary、d.name、d.budget、および e.isManager が使用されています。これらの例では、索引がエンティティーまたは値オブジェクトの名前、給与、および予算フィールドに対して定義済みであることを前提としています。empid フィールドは 1 次キーであり、isManager には索引が定義されていません。

以下の照会では、名前と給与の両フィールドに対して索引を使用します。この場合、名前が最初のパラメーターの値に一致するか、給与が 2 番目のパラメーターの値に一致するすべての従業員が戻されます。

SELECT e FROM EmpBean e where e.name=?1 or e.salary=?2

以下の照会では、名前と予算の両フィールドに対して索引を使用します。この照会は、2000 より大きい予算を持つ 'DEV' という名前の付いたすべての部門を戻します。

SELECT d FROM DeptBean dwhere d.name='DEV' and d.budget>2000

以下の照会では、給与が 3000 より高く、かつパラメーターの値と等しい isManager フラグ値を持つ従業員をすべて戻します。この照会では、給与フィールドに対して定義された索引を使用するとともに、比較式 e.isManager=?1. を評価することで追加のフィルタリングを実行します。

SELECT e FROM EmpBean e where e.salary>3000 and e.isManager=?1

次の照会では、1 番目のパラメーターより大きい給与を得ているか、または管理者である従業員をすべて検索します。給与フィールドには索引が定義済みですが、照会では、EmpBean フィールドの 1 次キーに対して作成された組み込み索引をスキャンし、式 e.salary>?1 または e.isManager=TRUE を評価します。

SELECT e FROM EmpBean e WHERE e.salary>?1 or e.isManager=TRUE

以下の照会では、文字 a が含まれている名前の従業員を戻します。名前フィールドには索引が定義済みですが、名前フィールドが LIKE 式で使用されているため、照会ではこの索引を使用しません。

SELECT e FROM EmpBean e WHERE e.name LIKE '%a%'

以下の照会では、名前が「Smith」ではない従業員をすべて検索します。名前フィールドには索引が定義済みですが、照会では等しくない ( <> ) 比較演算子を使用するため、この索引を使用しません。

SELECT e FROM EmpBean e where e.name<>'Smith'

以下の照会では、予算がパラメーターの値より小さく、かつ従業員給与が 3000 より大きい部門をすべて検索します。この照会では、給与の索引を使用しますが、dept.budget がシンプル・タームではないため、予算の索引を使用しません。dept オブジェクトは、コレクション e から導き出されます。dept オブジェクトを検索するのに、予算の索引を使用する必要はありません。

SELECT dept from EmpBean e, in (e.dept) dept where e.salary>3000 and dept.budget<?

以下の照会では、1、2、および 3 の empid を持つ従業員の給与より大きい給与の従業員をすべて検索します。比較には副照会が含まれているため、索引 salary は使用されません。empid は、1 次キーですが、すべての 1 次キーには組み込み索引が定義済みであるため、固有索引の検索に使用されます。

SELECT e FROM EmpBean e WHERE e.salary > ALL (SELECT e1.salary FROM EmpBean e1 WHERE e1.empid=1 or e1.empid =2 or e1.empid=99)

索引が照会で使用されているかどうかを確認する場合は、照会計画を表示できます。 以下に、前述の照会の照会計画例を示します。

for q2 in EmpBean ObjectMap using INDEX SCAN
    filter ( q2.salary >ALL     temp collection defined as
       IteratorUnionIndex of

         for q3 in EmpBean ObjectMap using UNIQUE INDEX key=(1)
        )

         for q3 in EmpBean ObjectMap using UNIQUE INDEX key=(2)
        )

         for q3 in EmpBean ObjectMap using UNIQUE INDEX key=(99)
        )
       returning new Tuple( q3.salary )
   returning new Tuple( q2  )

for q2 in EmpBean ObjectMap using RANGE INDEX on salary with range(3000,)
     for q3 in  q2.dept
      filter ( q3.budget <  ?1 )
   returning new Tuple( q3  )

属性の索引付け

前に定義された制約付きで、 任意の単一属性タイプに対して索引を定義できます。

@Index を使用したエンティティー索引 の定義

エンティティーに索引を定義するには、 単にアノテーションを定義します。

Entities using annotations

 	@Entity
 	public class Employee {
 	@Id int empid;
 	@Index String name
 	@Index double salary
 	@ManyToOne Department dept;
}
@Entity
 	public class Department {
 	@Id int deptid;
 	@Index String name;
 	@Index double budget;
 	boolean isManager;
 	@OneToMany Collection<Employee> employees;
 	}

XML の使用

XML を使用して索引を定義することも できます。
 	Entities without annotations

 	public class Employee {
 	int empid;
 	String name
 	double salary
 	Department dept;
 	}
 	 
 	public class Department {
 	int deptid;
 	String name;
 	double budget;
 	boolean isManager;
 	Collection employees;
 	}
ObjectGrid XML with attribute indexes

<?xml version="1.0" encoding="UTF-8"?>
 	<objectGridConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 	xsi:schemaLocation="http://ibm.com/ws/objectgrid/config ../objectGrid.xsd"
 	xmlns="http://ibm.com/ws/objectgrid/config">
 	<objectGrids>
 	<objectGrid name="DepartmentGrid" entityMetadataXMLFile="entity.xml>
 	<backingMap name="Employee" pluginCollectionRef="Emp"/>
 	<backingMap name="Department" pluginCollectionRef="Dept"/>
 	</objectGrid>
 	</objectGrids>
 	<backingMapPluginCollections>
 	<backingMapPluginCollection id="Emp">
 	<bean id="MapIndexPlugin" className="com.ibm.websphere.objectgrid.plugins.index.HashIndex">
 	<property name="Name" type="java.lang.String" value="Employee.name"/>
 	<property name="AttributeName" type="java.lang.String" value="name"/>
 	<property name="RangeIndex" type="boolean" value="true"
 	description="Ranges are must be set to true for attributes." />
 	</bean>
 	<bean id="MapIndexPlugin" className="com.ibm.websphere.objectgrid.plugins.index.HashIndex">
 	<property name="Name" type="java.lang.String" value="Employee.salary"/>
 	<property name="AttributeName" type="java.lang.String" value="salary"/>
 	<property name="RangeIndex" type="boolean" value="true"
 	description="Ranges are must be set to true for attributes." />
 	</bean>
 	</backingMapPluginCollection>
 	<backingMapPluginCollection id="Dept">
 	<bean id="MapIndexPlugin" className="com.ibm.websphere.objectgrid.plugins.index.HashIndex">
 	<property name="Name" type="java.lang.String" value="Department.name"/>
 	<property name="AttributeName" type="java.lang.String" value="name"/>
 	<property name="RangeIndex" type="boolean" value="true"
 	description="Ranges are must be set to true for attributes." />
 	</bean>
 	<bean id="MapIndexPlugin" className="com.ibm.websphere.objectgrid.plugins.index.HashIndex">
 	<property name="Name" type="java.lang.String" value="Department.budget"/>
 	<property name="AttributeName" type="java.lang.String" value="budget"/>
 	<property name="RangeIndex" type="boolean" value="true"
 	description="Ranges are must be set to true for attributes." />
 	</bean>
 	</backingMapPluginCollection>
 	</backingMapPluginCollections>
 	</objectGridConfig>
Entity XML

<?xml version="1.0" encoding="UTF-8"?>
 	<entity-mappings xmlns="http://ibm.com/ws/projector/config/emd"
 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 	xsi:schemaLocation="http://ibm.com/ws/projector/config/emd ./emd.xsd">
 	 
 	<description>Department entities</description>
 	<entity class-name="acme.Employee" name="Employee" access="FIELD">
 	<attributes>
 	<id name="empid" />
 	<basic name="name" />
 	<basic name="salary" />
 	<many-to-one name="department"
 	target-entity="acme.Department"
 	fetch="EAGER">
 	<cascade><cascade-persist/></cascade>
 	</many-to-one>
 	</attributes>
 	</entity>
 	<entity class-name="acme.Department" name="Department" access="FIELD">
 	<attributes>
 	<id name="deptid" />
 	<basic name="name" />
 	<basic name="budget" />
 	<basic name="isManager" />
 	<one-to-many name="employees"
 	target-entity="acme.Employee"
 	fetch="LAZY" mapped-by="parentNode">
 	<cascade><cascade-persist/></cascade>
 	</one-to-many>
 	</attributes>
 	</entity>
 	</entity-mappings>

XML を使用した非エンティティーの索引の定義

非エンティティー・タイプに 対する索引は XML 内で定義されます。MapIndexPlugin を作成するときに、 エンティティー・マップに対しての場合と非エンティティー・マップに対しての場合で相違はありません。

Java bean
public class Employee {
 	int empid;
 	String name
 	double salary
 	Department dept;

	public class Department {
 	int deptid;
 	String name;
 	double budget;
 	boolean isManager;
 	Collection employees;
 	}
ObjectGrid XML with attribute indexes

<?xml version="1.0" encoding="UTF-8"?>
 	<objectGridConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 	xsi:schemaLocation="http://ibm.com/ws/objectgrid/config ../objectGrid.xsd"
 	xmlns="http://ibm.com/ws/objectgrid/config">
 	<objectGrids>
 	<objectGrid name="DepartmentGrid">
 	<backingMap name="Employee" pluginCollectionRef="Emp"/>
 	<backingMap name="Department" pluginCollectionRef="Dept"/>
 	<querySchema>
 	<mapSchemas>
 	<mapSchema mapName="Employee" valueClass="acme.Employee"
 	primaryKeyField="empid" />
 	<mapSchema mapName="Department" valueClass="acme.Department"
 	primaryKeyField="deptid" />
 	</mapSchemas>
 	<relationships>
 	<relationship source="acme.Employee"
 	target="acme.Department"
 	relationField="dept" invRelationField="employees" />
 	</relationships>
 	</querySchema>
 	</objectGrid>
 	</objectGrids>
 	<backingMapPluginCollections>
 	<backingMapPluginCollection id="Emp">
 	<bean id="MapIndexPlugin" className="com.ibm.websphere.objectgrid.plugins.index.HashIndex">
 	<property name="Name" type="java.lang.String" value="Employee.name"/>
 	<property name="AttributeName" type="java.lang.String" value="name"/>
 	<property name="RangeIndex" type="boolean" value="true"
 	description="Ranges are must be set to true for attributes." />
 	</bean>
 	<bean id="MapIndexPlugin" className="com.ibm.websphere.objectgrid.plugins.index.HashIndex">
 	<property name="Name" type="java.lang.String" value="Employee.salary"/>
 	<property name="AttributeName" type="java.lang.String" value="salary"/>
 	<property name="RangeIndex" type="boolean" value="true"
 	description="Ranges are must be set to true for attributes." />
 	</bean>
 	</backingMapPluginCollection>
 	<backingMapPluginCollection id="Dept">
 	<bean id="MapIndexPlugin" className="com.ibm.websphere.objectgrid.plugins.index.HashIndex">
 	<property name="Name" type="java.lang.String" value="Department.name"/>
 	<property name="AttributeName" type="java.lang.String" value="name"/>
 	<property name="RangeIndex" type="boolean" value="true"
 	description="Ranges are must be set to true for attributes." />
 	</bean>
 	<bean id="MapIndexPlugin" className="com.ibm.websphere.objectgrid.plugins.index.HashIndex">
 	<property name="Name" type="java.lang.String" value="Department.budget"/>
 	<property name="AttributeName" type="java.lang.String" value="budget"/>
 	<property name="RangeIndex" type="boolean" value="true"
 	description="Ranges are must be set to true for attributes." />
 	</bean>
 	</backingMapPluginCollection>
 	</backingMapPluginCollections>
 	</objectGridConfig>

索引付けのリレーションシップ

WebSphere eXtreme Scale は、関連エンティティーの外部キーを親オブジェクト内に保管します。エンティティーの場合、キーは基本となるタプルに保管されます。 非エンティティー・オブジェクトの場合、キーは親オブジェクトに明示的に保管されます。

リレーションシップ属性に索引を追加すると、循環参照を使用するか、IS NULL、IS EMPTY、SIZE、および MEMBER OF 照会フィルターを使用する照会をスピードアップすることができます。単一値関連と多値関連がともに、ObjectGrid 記述子 XML ファイル内に @Index アノテーションまたは HashIndex プラグイン構成を持つ場合があります。

@Index を使用したエンティティー・リレーションシップ索引の定義

以下の例では、@Index アノテーションのあるエンティティーを定義します。

Entity with annotation

@Entity
public class Node {
    @ManyToOne @Index
    Node parentNode;

    @OneToMany @Index
    List<Node> childrenNodes = new ArrayList();

    @OneToMany @Index
    List<BusinessUnitType> businessUnitTypes = new ArrayList();
}

XML を使用したエンティティー・リレーションシップ索引の定義

以下の例は、XML と HashIndex プラグインを使用して、 同じエンティティーおよび索引を定義しています。

 	Entity without annotations

 	public class Node {
 	int nodeId;
 	Node parentNode;
 	List<Node> childrenNodes = new ArrayList();
 	List<BusinessUnitType> businessUnitTypes = new ArrayList();
 	}
ObjectGrid XML

<?xml version="1.0" encoding="UTF-8"?>
 	<objectGridConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 	xsi:schemaLocation="http://ibm.com/ws/objectgrid/config ../objectGrid.xsd"
 	xmlns="http://ibm.com/ws/objectgrid/config">
 	<objectGrids>
 	<objectGrid name="ObjectGrid_Entity" entityMetadataXMLFile="entity.xml>
 	<backingMap name="Node" pluginCollectionRef="Node"/>
 	<backingMap name="BusinessUnitType" pluginCollectionRef="BusinessUnitType"/>
 	</objectGrid>
 	</objectGrids>
 	<backingMapPluginCollections>
 	<backingMapPluginCollection id="Node">
 	<bean id="MapIndexPlugin" className="com.ibm.websphere.objectgrid.plugins.index.HashIndex">
 	<property name="Name" type="java.lang.String" value="parentNode"/>
 	<property name="AttributeName" type="java.lang.String" value="parentNode"/>
<property name="RangeIndex" type="boolean" value="false"
 	description="Ranges are not supported for association indexes." /> 	</bean>
 	<bean id="MapIndexPlugin" className="com.ibm.websphere.objectgrid.plugins.index.HashIndex">
 	<property name="Name" type="java.lang.String" value="businessUnitType"/>
 	<property name="AttributeName" type="java.lang.String" value="businessUnitTypes"/>

<property name="RangeIndex" type="boolean" value="false"
 	description="Ranges are not supported for association indexes." />
	</bean>
 	<bean id="MapIndexPlugin" className="com.ibm.websphere.objectgrid.plugins.index.HashIndex">
 	<property name="Name" type="java.lang.String" value="childrenNodes"/>
 	<property name="AttributeName" type="java.lang.String" value="childrenNodes"/>
<property name="RangeIndex" type="boolean" value="false"
 	description="Ranges are not supported for association indexes." />
 	</bean>
 	</backingMapPluginCollection>
 	</backingMapPluginCollections>
 	</objectGridConfig>
 	 
 Entity XML

 	<?xml version="1.0" encoding="UTF-8"?>
 	<entity-mappings xmlns="http://ibm.com/ws/projector/config/emd"
 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 	xsi:schemaLocation="http://ibm.com/ws/projector/config/emd ./emd.xsd">
 	 
 	<description>My entities</description>
 	<entity class-name="acme.Node" name="Account" access="FIELD">
 	<attributes>
 	<id name="nodeId" />
 	<one-to-many name="childrenNodes"
 	target-entity="acme.Node"
 	fetch="EAGER" mapped-by="parentNode">
 	<cascade><cascade-all/></cascade>
 	</one-to-many>
 	<many-to-one name="parentNodes"
 	target-entity="acme.Node"
 	fetch="LAZY" mapped-by="childrenNodes">
 	<cascade><cascade-none/></cascade>
 	</one-to-many>
 	<many-to-one name="businessUnitTypes"
 	target-entity="acme.BusinessUnitType"
 	fetch="EAGER">
 	<cascade><cascade-persist/></cascade>
 	</many-to-one>
</attributes>
 	</entity>
 	<entity class-name="acme.BusinessUnitType" name="BusinessUnitType" access="FIELD">
 	<attributes>
 	<id name="buId" />
 	<basic name="TypeDescription" />
 	</attributes>
 	</entity>
 	</entity-mappings>

前に定義された索引を使用すると、以下の例のエンティティー照会が最適化されます。

SELECT n FROM Node n WHERE n.parentNode is null
SELECT n FROM Node n WHERE n.businessUnitTypes is EMPTY
 	SELECT n FROM Node n WHERE size(n.businessUnitTypes)>=10
 	SELECT n FROM BusinessUnitType b, Node n WHERE b member of n.businessUnitTypes and b.name='TELECOM'

非エンティティー・リレーションシップ索引の 定義

以下の例では、ObjectGrid 記述子 XML ファイル内の非エンティティー・マップの HashIndex プラグインを定義します。

<?xml version="1.0" encoding="UTF-8"?>
<objectGridConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="http://ibm.com/ws/objectgrid/config ../objectGrid.xsd"
  xmlns="http://ibm.com/ws/objectgrid/config">
  <objectGrids>
    <objectGrid name="ObjectGrid_POJO">
      <backingMap name="Node" pluginCollectionRef="Node"/>
      <backingMap name="BusinessUnitType" pluginCollectionRef="BusinessUnitType"/>
      <querySchema>
        <mapSchemas>
          <mapSchema mapName="Node" 
					valueClass="com.ibm.websphere.objectgrid.samples.entity.Node"
            primaryKeyField="id" />
          <mapSchema mapName="BusinessUnitType"
            valueClass="com.ibm.websphere.objectgrid.samples.entity.BusinessUnitType"
            primaryKeyField="id" />
        </mapSchemas>
        <relationships>
          <relationship source="com.ibm.websphere.objectgrid.samples.entity.Node" 
            target="com.ibm.websphere.objectgrid.samples.entity.Node"
            relationField="parentNodeId" invRelationField="childrenNodeIds" />
          <relationship source="com.ibm.websphere.objectgrid.samples.entity.Node" 
            target="com.ibm.websphere.objectgrid.samples.entity.BusinessUnitType"
            relationField="businessUnitTypeKeys" invRelationField="" />
        </relationships>
      </querySchema>
    </objectGrid>
  </objectGrids>
  <backingMapPluginCollections>
    <backingMapPluginCollection id="Node">
      <bean id="MapIndexPlugin" className="com.ibm.websphere.objectgrid.plugins.index.HashIndex">
        <property name="Name" type="java.lang.String" value="parentNode"/>
<property name="Name" type="java.lang.String" value="parentNodeId"/>
<property name="AttributeName" type="java.lang.String" value="parentNodeId"/>
<property name="RangeIndex" type="boolean" value="false"
 	description="Ranges are not supported for association indexes." />
      </bean>
      <bean id="MapIndexPlugin" className="com.ibm.websphere.objectgrid.plugins.index.HashIndex">
        <property name="Name" type="java.lang.String" value="businessUnitType"/>
        <property name="AttributeName" type="java.lang.String" value="businessUnitTypeKeys"/>

<property name="RangeIndex" type="boolean" value="false"
 	description="Ranges are not supported for association indexes." />
   </bean>
      <bean id="MapIndexPlugin" className="com.ibm.websphere.objectgrid.plugins.index.HashIndex">
<property name="Name" type="java.lang.String" value="childrenNodeIds"/>
 	<property name="AttributeName" type="java.lang.String" value="childrenNodeIds"/>     
  <property name="RangeIndex" type="boolean" value="false"
 					description="Ranges are not supported for association indexes." />
</bean>
    </backingMapPluginCollection>
  </backingMapPluginCollections>
</objectGridConfig>

上記の索引構成が指定されると、以下の例のオブジェクト照会が最適化されます。

SELECT n FROM Node n WHERE n.parentNodeId is null
SELECT n FROM Node n WHERE n.businessUnitTypeKeys is EMPTY
SELECT n FROM Node n WHERE size(n.businessUnitTypeKeys)>=10
SELECT n FROM BusinessUnitType b, Node n WHERE 
	b member of n.businessUnitTypeKeys and b.name='TELECOM'