Pergunta

Eu tenho essa consulta MySQL que estou tentando analisar. É muito lento, a tabela de visitantes aqui são cerca de 50 mil entradas, essa consulta nunca retorna. Quando tentei uma declaração de explicação, descobri que o índice não está sendo usado na tabela de visitantes, apesar do índice estar disponível. Agora este é o grande quebra -cabeça que preciso de ajuda para resolver. Quaisquer dicas apreciadas.

Consulta:

select distinct
  visitor0_.ID as ID130_,      

  case when visitor0_1_.id is not null then 1 when
  visitor0_.ID is not null then 0
  end as clazz_

from Visitor visitor0_ 
left outer join Operator visitor0_1_ on visitor0_.ID=visitor0_1_.id
where (visitor0_.ID not in
    (select operator1_.id 
     from Operator operator1_ 
     inner join Visitor operator1_1_ on operator1_.id=operator1_1_.ID))
  and (exists 
    (select visitorpro2_.ID 
     from VisitorProfileField visitorpro2_, ProfileField profilefie3_ 
     where visitorpro2_.profileFieldID=profilefie3_.ID 
       and visitorpro2_.visitorID=visitor0_.ID 
       and profilefie3_.name='subscription86' 
       and visitorpro2_.numberVal=1 
       and visitorpro2_.stringVal='Manual'))

Explique a captura de tela de saída:http://grab.by/grabs/9c3a629a25fc4e9ec0fa54355d4a092c.png

Foi útil?

Solução

Pelo que deduo da sua consulta, o seguinte deve produzir o mesmo resultado, sem subconsulta e desempenho muito mais rápido.

select v.ID as ID130_, 0 as clazz_
from Visitor v
left outer join (VisitorProfileField vpf join ProfileField pf 
                   on vpf.profileFieldID = pf.ID)
  on v.ID = vpf.visitorID and pf.name='subscription86' 
    and vpf.numberVal=1 and vpf.stringVal='Manual'
left outer join Operator o on v.ID = o.ID
where o.ID IS NULL;

Por favor, explique se eu entendi um pouco errado. Parece que o seu NOT IN predicado exclui qualquer Visitor ID que corresponde a qualquer ID está em Operator. Isto é, a subconsência gera uma lista de tudo ID que está em ambas as tabelas, então o NOT IN a condição é equivalente a uma união externa para Operator e um teste simples onde o.ID IS NULL.

Isso significa o CASE A expressão na sua lista de seleção não tem sentido, pois certamente será 0 se suas condições corresponderem apenas Visitor linhas que não correspondem a nenhuma linha em Operator.

Eu acho que algo está seriamente confuso em sua consulta.

Além disso, parece que você está usando o Antipattern Eav no VisitorProfileField e ProfileField mesas. Isso vai causar muitos problemas.

Outras dicas

Você está consulta é ... grande. Você pode explicar o que isso atribui para você? Parece que ele puxa cada ID do visitante e se eles são ou não um operador, onde não são um operador e têm uma configuração de perfil específica. Isso não faz muito sentido, então devo estar perdendo algo lá.

Aqui está minha tentativa, com base na minha compreensão do que você está tentando fazer:

select distinct visitor.ID, IF(operator.id IS NOT NULL, 1, 0) AS clazz
from Visitor left outer join Operator on visitor.ID = operator.id
where not exists 
    (select 'x' from Operator OperatorTwo where OperatorTwo.id = visitor.ID)
and exists
    (select 'x' from VisitorProfileField, ProfileField
        where VisitorProfileField.profileFieldID = ProfileField.ID
        and VisitorProfileField.profileFieldID.visitorID = visitor.ID
        and VisitorProfileField.profileFieldID.numberVal = 1
        and VisitorProfileField.profileFieldID.stringVal = 'Manual'
        and ProfileField .name = 'subscription86')

A tabela ingressada chamada "Operator1_1_" não parece ser usada, você deve remover isso. Se você o estiver usando apenas para garantir que haja um registro para o visitante nessa tabela, eu usaria um existe em vez de uma junção. Eu deixei cair isso.

Eu desliguei você para não existir, o que acho que pode ser mais fácil para o MySQL otimizar. Eu usei um caso se em vez de um caso, porque você tem apenas dois e foi mais curto para digitar. Não sei se um deles é mais rápido/mais fácil no MySQL.

Posso dizer -lhe que, na minha experiência, o MySQL Performance morre com subconsciência em suformas. Parece desistir de otimizá -los e começa a executá -los de linha por linha. Aposto que, se você usasse uma tabela temporária de resultados (apenas para fins de teste), encontraria sua consulta muito mais rapidamente.

Editar:

Bill foi além do que eu, não fui longe o suficiente. Gosto da consulta de Bill e concordo com suas conclusões sobre a declaração do caso, que estava meio que me jogando.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top