Otimize o SQL com interbase
Pergunta
Eu fui inspirado pelas boas respostas do meu anterior pergunta Sobre SQL. Agora, este SQL é executado em um db com o Interbase 2009. É de cerca de 21 GB de tamanho.
SELECT DistanceAsMeters, AddrDistance.Bold_Id, AddrDistance.Created, AddressFrom.CityName_CO as FromCity, AddressTo.CityName_CO as ToCity
FROM AddrDistance
LEFT JOIN Address AddressFrom ON AddrDistance.FromAddress = AddressFrom.Bold_Id
LEFT JOIN Address AddressTo ON AddrDistance.ToAddress = AddressTo.Bold_Id
Where DistanceAsMeters = 0 and PseudoDistanceAsCostKm = 0
and not AddrDistance.bold_id in (select bold_id from DistanceQueryTask)
Order By Created Desc
Existem 840000 linhas com linhas addrdistance 190000 com endereço e 4 com o DOURSOQUERYTASK.
A questão é: isso pode ser feito mais rápido? Eu acho, a mesma consulta é executada muitas vezes Selecione Bold_Id de DistanceyTask. Observe que não estou interessado em procedimentos armazenados, apenas SQL simples :)
Edit1 Aqui está o plano de execução atual:
Statement: SELECT DistanceAsMeters, AddrDistance.Bold_Id, AddrDistance.Created, AddressFrom.CityName_CO as FromCity, AddressTo.CityName_CO as ToCity
FROM AddrDistance
LEFT JOIN Address AddressFrom ON AddrDistance.FromAddress = AddressFrom.Bold_Id
LEFT JOIN Address AddressTo ON AddrDistance.ToAddress = AddressTo.Bold_Id
Where DistanceAsMeters = 0 and PseudoDistanceAsCostKm = 0
and not AddrDistance.bold_id in (select bold_id from DistanceQueryTask)
Order By Created Desc
PLAN (DISTANCEQUERYTASK INDEX (RDB$PRIMARY218))
PLAN SORT (JOIN (JOIN (ADDRDISTANCE NATURAL,ADDRESSFROM INDEX (RDB$PRIMARY234)),ADDRESSTO INDEX (RDB$PRIMARY234)))
E sim, o DOURSQUERYTASK deve ter um número baixo se linhas no banco de dados.
Solução
Usar a junção esquerda e as subconsminações desacelerará qualquer consulta.
Você pode obter algumas melhorias com os índices corretos (em Bold_id, Distancemeter, PseudodistanCeasCostkm) Lembre -se de que mais índices aumentam o tamanho do banco de dados
Outras dicas
Suponho que Bold_Id é a sua chave e, portanto, devidamente indexado.
Em seguida, substituir o subseleto e o não ... por uma junção pode ajudar o otimizador.
SELECT DistanceAsMeters, Bold_Id, Created, AddressFrom.CityName_CO as FromCity, AddressTo.CityName_CO as ToCity
FROM AddrDistance
LEFT JOIN Address AddressFrom ON AddrDistance.FromAddress = AddressFrom.Bold_Id
LEFT JOIN Address AddressTo ON AddrDistance.ToAddress = AddressTo.Bold_Id
LEFT JOIN DistanceQueryTask ON AddrDistance.bold_id = DistanceQueryTask.bold_id
Where DistanceAsMeters = 0 and PseudoDistanceAsCostKm = 0
and DistanceQueryTask.bold_id is null
Order By Created Desc
Crie um índice para esta parte: (DistancEasMeters = 0 e PseudodistanCeascostkm = 0) porque faz uma (Bad) Tabela Scan para ele: Addrdistance Natural Natural
E tente usar a junção em vez de subseleção, conforme declarado pelo François.
Como Daniel e Andre Sugers, um índice ajuda muito.
Eu sugeriria que esse índice (Distancemeter, PseudodistanCeascostkm, Bold_id), porque as duas primeiras partes do índice são constantes, então é uma parte smal do índice que é necessário para ler.
Se for um fato que a FromAddress e/ou a Toaddress existem, você pode alterar a junção esquerda para a junção interna, porque geralmente é mais rápida (o otimizador de consulta pode fazer algumas suposições).