Plano de Consulta

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:

Método getPlan

O método getPlan nas interfaces ObjectQuery e Query retorna uma String que descreve o plano de consulta. Esta cadeia pode ser exibida na saída padrão ou no log para exibir um plano de consulta.
Nota: Em um ambiente distribuído, o método getPlan não é executado junto ao servidor e não refletirá nenhum índice definido. Para visualizar o plano, utilize um agente para visualizar o plano no servidor.

Rastreio de Plano de Consulta

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.

Exemplos de Plano de Consulta

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  )