La definición y el uso correctos de índices puede mejorar significativamente el rendimiento de las consultas.
Las consultas de WebSphere eXtreme Scale pueden utilizar los plug-ins HashIndex incorporados para mejorar el rendimiento de las consultas. Los índices se pueden definir en atributos de entidad o de objeto. El motor de consultas utilizará automáticamente los índices definidos si su cláusula WHERE utiliza una de las series siguientes:
Para obtener información sobre cómo configurar HashIndex, consulte Plug-ins para la indexación de datos.
Para obtener información acerca de la indexación, consulte Índices.
Para obtener información sobre un modo eficaz de buscar objetos almacenados en memoria caché, consulte el apartado Utilización de un índice compuesto.
Se puede seleccionar manualmente un índice utilizando el método setHint en las interfaces Query y ObjectQuery con la constante HINT_USEINDEX. Esto puede ser útil al optimizar una consulta para utilizar el índice con mejor rendimiento.
Los ejemplos siguientes utilizan términos simples: e.empid, e.name, e.salary, d.name, d.budget y e.isManager. En el ejemplo se da por supuesto que los índices se han definido en los campos de nombre, salario y presupuesto de un objeto de entidad o valor. El campo empid es una clave primaria e isManager no tiene ningún índice definido.
La consulta siguiente utiliza los índices en los campos de nombre y salario. Devuelve todos los empleados con nombres que son iguales al valor del primer parámetro o un salario que es igual al valor del segundo parámetro:
SELECT e FROM EmpBean e where e.name=?1 or e.salary=?2
La siguiente consulta utiliza ambos índices en los campos de nombre y presupuesto. La consulta devuelve todos los departamentos con nombre 'DEV' que tienen un presupuesto que es mayor que 2000.
SELECT d FROM DeptBean dwhere d.name='DEV' and d.budget>2000
La consulta siguiente devuelve todos los empleados con un salario mayor que 3000 y con un valor de distintivo isManager que es igual al valor del parámetro. La consulta utiliza el índice que se ha definido en el campo de salario y realiza un filtrado adicional al evaluar la expresión de comparación: e.isManager=?1.
SELECT e FROM EmpBean e where e.salary>3000 and e.isManager=?1
La consulta siguiente busca todos los empleados que ganan más que el primer parámetro o los empleados que son jefes. Aunque el campo de salario tiene un índice definido, la consulta explora el índice incorporado que se ha creado en las claves primarias del campo EmpBean y evalúa la expresión: e.salary>?1 o e.isManager=TRUE.
SELECT e FROM EmpBean e WHERE e.salary>?1 or e.isManager=TRUE
La consulta siguiente devuelve los empleados con un nombre que contiene la letra a. Aunque el campo de nombre tiene un índice definido, la consulta no utiliza el índice porque el campo de nombre se utiliza en la expresión LIKE.
SELECT e FROM EmpBean e WHERE e.name LIKE '%a%'
La consulta siguiente busca todos los empleados con un nombre que no sea "Smith". Aunque el campo de nombre tiene un índice definido, la consulta no utiliza el índice porque la consulta utiliza el operador de comparación distinto ( <> ).
SELECT e FROM EmpBean e where e.name<>'Smith'
La consulta siguiente busca todos los departamentos con un presupuesto inferior al valor del parámetro, y con un salario de empleados superior a 3000. La consulta utiliza un índice para el salario, pero no utiliza un índice para el presupuesto porque dept.budget no es un término simple. Los objetos dept se derivan de la colección e. No es necesario utilizar el índice de presupuesto para buscar los objetos dept.
SELECT dept from EmpBean e, in (e.dept) dept where e.salary>3000 and dept.budget<?
La consulta siguiente busca todos los empleados con un salario superior al salario de los empleados que tienen empid de 1, 2 y 3. No se utiliza el salario de índice porque la comparación tiene una subconsulta. empid es una clave primaria, y se utiliza para una búsqueda de índice único porque todas las claves primarias tienen un índice incorporado definido.
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)
Para comprobar si la consulta utiliza el índice, puede consultar el apartado Plan de consulta. A continuación se muestra un plan de consulta de ejemplo de la consulta anterior:
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 )
Los índices se pueden definir con un único tipo de atributo con las restricciones definidas previamente.
Definición de índices de entidad utilizando @Index
Para definir un índice en una entidad, simplemente defina una anotación:
Entidades que utilizan anotaciones
@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;
}
Con XML
Entidades sin anotaciones
public class Employee {
int empid;
String name
double salary
Department dept;
}
public class Department {
int deptid;
String name;
double budget;
boolean isManager;
Collection employees;
}
XML de ObjectGrid con índices de atributo
<?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="Se deben establecer los rangos en true para los atributos." />
</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="Se deben establecer los rangos en true para los atributos." />
</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="Se deben establecer los rangos en true para los atributos." />
</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="Se deben establecer los rangos en true para los atributos." />
</bean>
</backingMapPluginCollection>
</backingMapPluginCollections>
</objectGridConfig>
XML de entidad
<?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>
Definición de índices para no entidades utilizando XML
Los índices para tipos que no son entidad están definidos en XML. No hay ninguna diferencia al crear MapIndexPlugin para correlaciones con entidad y correlaciones sin entidad.
Bean de Java
public class Employee {
int empid;
String name
double salary
Department dept;
public class Department {
int deptid;
String name;
double budget;
boolean isManager;
Collection employees;
}
XML de ObjectGrid con índices de atributo
<?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="Se deben establecer los rangos en true para los atributos." />
</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="Se deben establecer los rangos en true para los atributos." />
</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="Se deben establecer los rangos en true para los atributos." />
</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="Se deben establecer los rangos en true para los atributos." />
</bean>
</backingMapPluginCollection>
</backingMapPluginCollections>
</objectGridConfig>
WebSphere eXtreme Scale almacena las claves foráneas para las entidades relacionadas dentro del objeto padre. En el caso de entidades, las claves se almacenan en el tuple subyacente. En el caso de objetos que no son de entidad, las claves se almacenan explícitamente en el objeto padre.
Si se añade un índice a un atributo de relación, se pueden acelerar las consultas que utilizan referencias cíclicas o los filtros de consulta IS NULL, IS EMPTY, SIZE y MEMBER OF. Las asociaciones de un valor o de varios valores pueden tener la anotación @Index o una configuración de plug-in HashIndex en un archivo XML de descriptor de ObjectGrid.
Definición de los índices de relación de entidad utilizando @Index
El ejemplo siguiente define las entidades con las anotaciones @Index:
Entidad con anotación
@Entity
public class Node {
@ManyToOne @Index
Node parentNode;
@OneToMany @Index
List<Node> childrenNodes = new ArrayList();
@OneToMany @Index
List<BusinessUnitType> businessUnitTypes = new ArrayList();
}
Definición de índices de relación utilizando XML
El ejemplo siguiente define las mismas entidades e índices utilizando XML con los plug-ins HashIndex:
Entidad sin anotaciones
public class Node {
int nodeId;
Node parentNode;
List<Node> childrenNodes = new ArrayList();
List<BusinessUnitType> businessUnitTypes = new ArrayList();
}
XML de ObjectGrid
<?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="Los rangos no están soportados para los índices de asociación." /> </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="Los rangos no están soportados para los índices de asociación." />
</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="Los rangos no están soportados para los índices de asociación." />
</bean>
</backingMapPluginCollection>
</backingMapPluginCollections>
</objectGridConfig>
XML de entidad
<?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>
A través de los índices definidos previamente, se optimizan los siguientes ejemplos de consulta de entidad:
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'
Definición de índices de relación sin entidad
En el ejemplo siguiente se define un plug-in HashIndex para correlaciones que no son de entidad en un archivo XML de descriptor de ObjectGrid:
<?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="Los rangos no están soportados para los índices de asociación." />
</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="Los rangos no están soportados para los índices de asociación." />
</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="Los rangos no están soportados para los índices de asociación." />
</bean>
</backingMapPluginCollection>
</backingMapPluginCollections>
</objectGridConfig>
Dadas las configuraciones de índice anteriores, se optimizan los ejemplos de consulta de objetos siguientes:
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'