Todas as consultas do eXtreme Scale possuem um plano de consulta. O plano descreve como o mecanismo de consulta interage com os ObjectMaps e índices. Exiba o plano de consulta para determinar se a cadeia de consulta ou índices estão sendo utilizados apropriadamente. O plano de consulta também pode ser usado para explorar as diferenças que as mudanças repentinas em uma sequência de consultas fazem na maneira que o eXtreme Scale executa uma consulta.
O plano de consulta pode ser visualizado de uma de duas maneiras:
O plano de consulta pode ser exibido utilizando o rastreio do ObjectGrid. Para ativar o rastreio de plano de consulta, utilize a seguinte especificação de rastreio:
QueryEnginePlan=debug=enabled
Consulte Coletando Rastreio para obter detalhes sobre como ativar o rastreio e localizar os arquivos de log de rastreio.
O plano de consulta usa a palavra para indicar que a consulta está iterando por meio de uma coleção do ObjectMap ou por meio de uma coleção derivada, tal como: q2.getEmps(), q2.dept, ou uma coleção temporária retornada por um loop interno. Se a coleção for a partir de um ObjectMap, o plano de consulta mostrará se uma varredura sequencial (denotada por por INDEX SCAN), índice exclusivo ou não exclusivo, é usado. Planos de consulta utilizam uma cadeia de filtros para lista as expressões de consulta aplicadas a uma coleta.
Geralmente, um produto cartesiano não é utilizado na consulta do objeto. A consulta a seguir varre o mapa EmpBean inteiro no loop externo e varre o mapa DeptBean inteiro no loop interno:
SELECT e, d FROM EmpBean e, DeptBean d
Plan trace:
for q2 in EmpBean ObjectMap using INDEX SCAN
for q3 in DeptBean ObjectMap using INDEX SCAN
returning new Tuple( q2, q3 )
A consulta a seguir recupera todos os nomes de funcionários a partir de um departamento específico ao varrer sequencialmente o mapa EmpBean para obter um objeto employee. A partir do objeto employee, a consulta navega até seu objeto department e aplica o filtro d.no=1. Neste exemplo, cada funcionário possui apenas uma referência de objeto departamento, assim o loop interno é executado uma vez:
SELECT e.name FROM EmpBean e JOIN e.dept d WHERE d.no=1
Plan trace:
for q2 in EmpBean ObjectMap using INDEX SCAN
for q3 in q2.dept
filter ( q3.getNo() = 1 )
returning new Tuple( q2.name )
O exemplo a seguir é equivalente à consulta anterior. Entretanto, a consulta a seguir executa melhor porque ela primeiro limita o resultado para um objeto departamento ao usar o índice exclusivo que é definido sobre o número do campo de chave primária DeptBean. A partir do objeto department, a consulta navega para os seus objetos employee para obter seus nomes:
SELECT e.name FROM DeptBean d JOIN d.emps e WHERE d.no=1
Plan trace:
for q2 in DeptBean ObjectMap using UNIQUE INDEX key=(1)
for q3 in q2.getEmps()
returning new Tuple( q3.name )
A consulta a seguir localiza todos os funcionários que trabalham em desenvolvimento ou vendas. A consulta varre o mapa EmpBean inteiro e executa filtragem adicional avaliando as expressões: d.name = 'Sales' ou d.name='Dev'
SELECT e FROM EmpBean e, in (e.dept) d WHERE d.name = 'Sales' or d.name='Dev'
Plan trace:
for q2 in EmpBean ObjectMap using INDEX SCAN
for q3 in q2.dept
filter (( q3.getName() = Sales ) OR ( q3.getName() = Dev ) )
returning new Tuple( q2 )
A consulta a seguir é equivalente à consulta anterior, mas esta consulta executa um plano de consulta diferente e utiliza o índice de intervalo baseado no nome do campo. Em geral, esta consulta desempenha melhor porque o índice sobre o nome do campo é utilizado para restringir em objetos de departamentos, o que é executado mais rapidamente se apenas alguns departamentos forem de desenvolvimento ou vendas.
SELECT e FROM DeptBean d, in(d.emps) e WHERE d.name='Dev' or d.name='Sales'
Plan trace:
IteratorUnionIndex of
for q2 in DeptBean ObjectMap using INDEX on name = (Dev)
for q3 in q2.getEmps()
for q2 in DeptBean ObjectMap using INDEX on name = (Sales)
for q3 in q2.getEmps()
A consulta a seguir localiza departamentos que não possuem nenhum funcionário:
SELECT d FROM DeptBean d WHERE NOT EXISTS(select e from d.emps e)
Plan trace:
for q2 in DeptBean ObjectMap using INDEX SCAN
filter ( NOT EXISTS ( correlated collection defined as
for q3 in q2.getEmps()
returning new Tuple( q3 )
returning new Tuple( q2 )
A consulta a seguir é equivalente à consulta anterior, mas utiliza a função escalar SIZE. Esta consulta possui desempenho semelhante, mas é mais fácil de gravar.
SELECT d FROM DeptBean d WHERE SIZE(d.emps)=0
for q2 in DeptBean ObjectMap using INDEX SCAN
filter (SIZE( q2.getEmps()) = 0 )
returning new Tuple( q2 )
O exemplo a seguir é uma outra forma de escrever a mesma consulta como a consulta anterior com desempenho semelhante, mas esta consulta também é mais fácil de escrever:
SELECT d FROM DeptBean d WHERE d.emps is EMPTY
Plan trace:
for q2 in DeptBean ObjectMap using INDEX SCAN
filter ( q2.getEmps() IS EMPTY )
returning new Tuple( q2 )
A consulta a seguir localiza quaisquer funcionários com um endereço inicial correspondendo a pelo menos um dos endereços do funcionário cujo nome seja igual ao valor do parâmetro. O loop interno não possui nenhuma dependência do loop externo. A consulta é executada no loop interno uma vez.
SELECT e FROM EmpBean e WHERE e.home = any (SELECT e1.home FROM EmpBean e1 WHERE e1.name=?1)
for q2 in EmpBean ObjectMap using INDEX SCAN
filter ( q2.home =ANY temp collection defined as
for q3 in EmpBean ObjectMap using INDEX on name = ( ?1)
returning new Tuple( q3.home )
)
returning new Tuple( q2 )
A consulta a seguir é equivalente à consulta anterior, mas possui uma subconsulta correlacionada; além disso, o loop interno é executado repetidamente.
SELECT e FROM EmpBean e WHERE EXISTS(SELECT e1 FROM EmpBean e1 WHERE e.home=e1.home and e1.name=?1)
Plan trace:
for q2 in EmpBean ObjectMap using INDEX SCAN
filter ( EXISTS ( correlated collection defined as
for q3 in EmpBean ObjectMap using INDEX on name = ( ?1)
filter ( q2.home = q3.home )
returning new Tuple( q3 )
returning new Tuple( q2 )