Definir e utilizar índices adequadamente pode aprimorar significativamente o desempenho da consulta.
As consultas do WebSphere eXtreme Scale podem usar plug-ins HashIndex integrados para aumentar o desempenho de consultas. Os índices podem ser definidos em atributos entity ou object. O mecanismo de consulta usará automaticamente os índices definidos se a sua cláusula WHERE usar uma das seguintes cadeias:
Para obter informações sobre a configuração do HashIndex, consulte o Plug-ins para Indexar Dados.
Para obter informações sobre a indexação, consulte o Indexação.
Para obter uma maneira mais eficiente de procurar objetos armazenados em cache, consulte Usando um Índice Composto
Um índice pode ser manualmente selecionado usando o método setHint nas interfaces Query e ObjectQuery com a constante HINT_USEINDEX. Isto pode ser útil quando a otimização de uma consulta usar o melhor índice de desempenho.
Os exemplos a seguir utilizam termos simples: e.empid, e.name, e.salary, d.name, d.budget e e.isManager. Os exemplos assumem que os índices são definidos sobre os campos name, salary e budget de um objeto entity ou value. O campo empid é uma chave primária e isManager não possui índice definido.
A consulta a seguir utiliza ambos os índices sobre o campos name e salary. Ela retorna todos os funcionários com nomes iguais ao valor do primeiro parâmetro ou um salário igual ao valor do segundo parâmetro:
SELECT e FROM EmpBean e where e.name=?1 or e.salary=?2
A consulta a seguir usa ambos índices sobre os campos de nome e orçamento. Ela retorna todos os departamentos nomeados 'DEV' com um orçamento que é maior que 2000.
SELECT d FROM DeptBean dwhere d.name='DEV' and d.budget>2000
A consulta a seguir retorna todos os funcionários com um salário maior do que 3000 e com um valor sinalizador isManager igual ao valor do parâmetro. A consulta utiliza o índice que é definido sobre o campo salary e executa filtragem adicional ao avaliar a expressão de comparação: e.isManager=?1.
SELECT e FROM EmpBean e where e.salary>3000 and e.isManager=?1
A consulta a seguir localiza todos os funcionários que ganham mais que o primeiro parâmetro ou que qualquer funcionário que é um gerente. Embora o campo salary tenha um índice definido, a consulta varre o índice integrado que é baseado em chaves primárias do campo EmpBean e avalia a expressão: e.salary>?1 ou e.isManager=TRUE.
SELECT e FROM EmpBean e WHERE e.salary>?1 or e.isManager=TRUE
A consulta a seguir retorna funcionários com um nome que contém a letra a. Embora o campo name tenha um índice definido, a consulta não utiliza o índice porque o campo name é utilizado na expressão LIKE.
SELECT e FROM EmpBean e WHERE e.name LIKE '%a%'
A consulta a seguir localiza todos os funcionários com um nome que não seja "Smith". Embora o campo name tenha um índice definido, a consulta não utiliza o índice porque a consulta utiliza o operador de comparação não iguais ( <> ).
SELECT e FROM EmpBean e where e.name<>'Smith'
A seguinte consulta localiza todos os departamentos com um orçamento menor do que o valor do parâmetro e com um salário superior a 3000. A consulta utiliza um índice para o salário, mas não utiliza um índice para o orçamento porque dept.budget não é um termo simples. Os objetos dept são derivados da coleta e. Não é necessário utilizar o índice de orçamento para consultar objetos dept.
SELECT dept from EmpBean e, in (e.dept) dept where e.salary>3000 and dept.budget<?
A consulta a seguir localiza todos os funcionários com um salário maior do que o salário dos funcionários que possuem o empid e 1, 2 e 3. O salário do índice não é utilizado porque a comparação envolve uma subconsulta. O empid é uma chave primária, entretanto, ele é utilizado para uma procura de índice exclusiva porque todas as chaves primárias possuem um índice integrado 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 verificar se o índice está sendo utilizado pela consulta, é possível visualizar o Plano de Consulta. A seguir, está um plano de consulta de exemplo para a 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 )
Os índices podem ser definidos sobre qualquer tipo de atributo único com os limitadores anteriormente definidos.
definição de índices de entidade usando @Index
Para definir um índice em uma entidade, simplesmente defina uma anotação:
Entidades usando anotações
@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;
}
Com XML
Entidades sem anotações
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 do ObjectGrid com índices de atributos
<?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>
Entidade 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>
Definição de índices para não-entidades usando XML
Os índices para tipos de não-entidade são definidos em XML. Não há diferença quando a criação do MapIndexPlugin para mapas de entidade e mapas de não-entidade.
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;
}
XML do ObjectGrid com índices de atributos
<?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>
O WebSphere eXtreme Scale armazena as chaves estrangeiras para entidades relacionadas dentro do objeto-pai. Para entidades, as chaves são armazenadas na tupla subjacente. Para objetos não-entidade, as chaves são explicitamente armazenadas no objeto-pai.
Incluir um índice em um atributo de relacionamento pode acelerar consultas que utilizam referências cíclicas ou utilizam os filtros de consulta IS NULL, IS EMPTY, SIZE e MEMBER OF. Ambas as associações únicas e com diversos valores podem ter a anotação @Index ou uma configuração de plug-in HashIndex em um arquivo XML descritor do ObjectGrid.
Definição de índices de relacionamento de entidade usando @Index
O exemplo a seguir define entidades com anotações @Index:
Entidade com anotação
@Entity
public class Node {
@ManyToOne @Index
Node parentNode;
@OneToMany @Index
List<Node> childrenNodes = new ArrayList();
@OneToMany @Index
List<BusinessUnitType> businessUnitTypes = new ArrayList();
}
Definição dos índices de relacionamento da entidade usando XML
O exemplo a seguir define as mesmas entidades e índices usando XML com plug-ins HashIndex:
Entidade sem anotações
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>
Entidade 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>
Usando os índices anteriormente definidos, os exemplos de consulta de entidades a seguir são otimizados:
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'
Definição dos índices de relacionamento de não-entidade
O exemplo a seguir define um plug-in HashIndex para mapas de não-entidade em um arquivo XML descritor do 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="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>
Dadas as configurações de índice acima, o exemplos de consulta do objeto são otimizados:
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'