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