Durch die ordnungsgemäße Definition und Verwendung von Indizes kann die Abfrageleistung erheblich verbessert werden.
eXtreme-Scale-Abfragen können integrierte HashIndex-Plug-ins verwenden, um die Leistung von Abfragen zu verbessern. Indizes können für Entitäts- oder Objektattribute definiert werden. Die Abfragesteuerkomponente verwendet automatisch die definierten Indizes, wenn in der WHERE-Klausel eine der folgenden Zeichenfolgen verwendet wird:
Weitere Informationen zum Konfigurieren des HashIndex finden Sie im Abschnitt Plug-ins für die Indexierung von Daten.
Informationen zur Indexierung finden Sie im Abschnitt Indexierung.
Eine effizientere Methode für die Suche zwischengespeicherter Objekte ist im Abschnitt Zusammengesetzten Index verwenden beschrieben.
Ein Index kann manuell über die Methode "setHint" in den Schnittstellen "Query" und "ObjectQuery" mit der Konstanten HINT_USEINDEX ausgewählt werden. Dies kann hilfreich sein, wenn eine Abfrage für die Verwendung des Index mit der besten Leistung optimiert wird.
In den folgenden Beispielen werden einfache Bedingungen verwendet: e.empid, e.name, e.salary, d.name, d.budget und e.isManager. In den Beispielen wird davon ausgegangen, dass Indizes über die Felder "name", "salary" und "budget" einer Entität oder eines Wertobjekts definiert werden. Das Feld "empid" ist ein Primärschlüssel, und für "isManager" ist kein Index definiert.
Die folgende Abfrage verwendet beide Indizes über die Felder "name" und "salary". Sie gibt alle Mitarbeiter (employees) zurück, deren Name dem Wert des ersten Parameters oder deren Gehalt (salary) dem Wert des zweiten Parameters entspricht:
SELECT e FROM EmpBean e where e.name=?1 or e.salary=?2
Die folgende Abfrage verwendet beide Indizes über die Felder "name" und "budget". Die Abfrage gibt alle Abteilungen (departments) mit dem Namen 'DEV' und einem Budget größer als 2000 zurück.
SELECT d FROM DeptBean dwhere d.name='DEV' and d.budget>2000
Die folgende Abfrage gibt alle Mitarbeiter mit einem Gehalt größer als 3000 zurück, deren isManager-Flag-Wert dem Wert des Parameters entspricht. Die Abfrage verwendet den Index, der über das Feld "salary" definiert wurde, und führt eine weitere Filterung durch, indem sie den folgenden Vergleichsausdruck auswertet: e.isManager=?1.
SELECT e FROM EmpBean e where e.salary>3000 and e.isManager=?1
Die folgende Abfrage sucht alle Mitarbeiter, deren Gehalt höher ist als der erste Parameter, bzw. alle Mitarbeiter, die Manager sind. Obwohl für das Feld "salary" ein Index definiert ist, scannt die Abfrage den integrierten Index, der über die Primärschlüssel des Felds "EmpBean" erstellt wurde, und wertet den folgenden Ausdruck aus: e.salary>?1 or e.isManager=TRUE.
SELECT e FROM EmpBean e WHERE e.salary>?1 or e.isManager=TRUE
Die folgende Abfrage gibt Mitarbeiter zurück, deren Name den Buchstaben a enthält. Obwohl für das Feld "name" ein Index definiert ist, verwendet die Abfrage den Index nicht, weil das Feld "name" im LIKE-Ausdruck verwendet wird.
SELECT e FROM EmpBean e WHERE e.name LIKE '%a%'
Die folgende Abfrage sucht alle Mitarbeiter, deren Name nicht "Smith" ist. Obwohl für das Feld "name" ein Index definiert ist, verwendet die Abfrage den Index nicht, weil die Abfrage den Vergleichsoperator ungleich (<>) verwendet.
SELECT e FROM EmpBean e where e.name<>'Smith'
Die folgende Abfrage sucht alle Abteilungen, deren Budget kleiner ist als der Wert des Parameters und deren Mitarbeitergehälter größer als 3000 sind. Die Abfrage verwendet einen Index für das Gehalt (salary), aber keinen Index für das Budget, weil dept.budget keine einfache Bedingung ist. Die dept-Objekte werden aus der Sammlung e abgeleitet. Sie müssen den Budgetindex nicht verwenden, um dept-Objekte zu suchen.
SELECT dept from EmpBean e, in (e.dept) dept where e.salary>3000 and dept.budget<?
Die folgende Abfrage sucht alle Mitarbeiter, deren Gehälter größer sind als die Gehälter der Mitarbeiter mit empid 1, 2 und 3. Der Index für das Feld "salary" wird nicht verwendet, weil der Vergleich eine Unterabfrage enthält. Der empid-Wert ist jedoch ein Primärschlüssel und wird für eine eindeutige Indexsuche verwendet, weil für alle Primärschlüssel ein integrierter Index definiert ist.
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)
Um zu prüfen, ob der Index von der Abfrage verwendet wird, können Sie den Abschnitt Abfrageplan verwenden. Im Folgenden sehen Sie einen Beispielabfrageplan für die vorherige Abfrage:
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 )
Indizes können über einen Einzelattributtyp mit den zuvor definierten Einschränkungen definiert werden.
Entitätsindizes mit @Index definieren
Wenn Sie einen Index für eine Entität definieren möchten, definieren Sie einfach eine Annotation:
Entitäten mit Annotationen
@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;
}
Mit XML
Entitäten ohne Annotationen
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 mit Attributindizes
<?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>
Entitäts-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>
Indizes mit XML für Objekte definieren, die keine Entitäten sind
Indizes für Objekte, die keine Entitäten sind, werden in XML definiert. Das MapIndexPlugin für Maps, die keine Entitäts-Maps sind, wird auf dieselbe Weise wie für Entitäts-Maps erstellt.
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 mit Attributindizes
<?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 speichert die Fremdschlüssel für zusammengehörige Entitäten im übergeordneten Objekt. Für Entitäten werden die Schlüssel im zugrunde liegenden Tupel gespeichert. Für Objekte, die keine Entitäten sind, werden die Schlüssel explizit im übergeordneten Objekt gespeichert.
Das Hinzufügen eines Index für ein Beziehungsattribut kann Abfragen beschleunigen, die zyklische Referenzen oder die Abfragefilter IS NULL, IS EMPTY, SIZE und MEMBER OF verwenden. Sowohl Assoziationen mit einem Wert als auch Assoziationen mit mehreren Werten können die Annotation "@Index" oder eine HashIndex-Plug-in-Konfiguration in einer ObjectGrid-XML-Deskriptordatei enthalten.
Entitätsbeziehungsindizes mit @Index definieren
Im folgenden Beispiel werden Entitäten mit @Index-Annotationen definiert:
Entität mit Annotation
@Entity
public class Node {
@ManyToOne @Index
Node parentNode;
@OneToMany @Index
List<Node> childrenNodes = new ArrayList();
@OneToMany @Index
List<BusinessUnitType> businessUnitTypes = new ArrayList();
}
Entitätsbeziehungsindizes mit XML definieren
Im folgenden Beispiel werden dieselben Entitäten und Indizes mit XML mit HashIndex-Plug-ins definiert:
Entität ohne Annotationen
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>
Entitäts-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>
Mit den zuvor definierten Indizes werden die folgenden Entitätsabfragebeispiele optimiert:
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'
Beziehungsindizes für Objekte definieren, die keine Entitäten sind
Im folgenden Beispiel wird ein HashIndex-Plug-in für Maps, die keine Entitäts-Maps sind, in einer ObjectGrid-XML-Deskriptordatei definiert:
<?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>
Mit den zuvor gezeigten Indexkonfigurationen werden die folgenden Objektabfragebeispiele optimiert:
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'