Executamos um site com 250 MM de linhas em uma tabela e em outra tabela à qual o associamos à maioria das consultas tem pouco menos de 15 MM de linhas.
Estruturas de amostra:
MasterTable (Id, UserId, Created, Updated...) -- 15MM Rows
DetailsTable (Id, MasterId, SomeColumn...) -- 250MM Rows
UserTable (Id, Role, Created, UserName...) -- 12K Rows
Regularmente, precisamos fazer algumas consultas em todas essas tabelas. Um deles é pegar estatísticas para usuários gratuitos (~ 10.000 usuários gratuitos).
Select Count(1) from DetailsTable dt
join MasterTable mt on mt.Id = dt.MasterId
join UserTable ut on ut.Id = mt.UserId
where ut.Role is null and mt.created between @date1 and @date2
O problema é que essa consulta algumas vezes demora muito, devido ao fato de as junções acontecerem muito antes do local.
Nesse caso, seria mais sensato usar wherees em vez de junções ou possivelmente where column in(...)
?
join
best-practices
Jeremy Boyd
fonte
fonte
Respostas:
Para RDBMS moderno, não há diferença entre "JOIN explícito" e "JOIN-in-the-WHERE" (se todas as JOINS forem INNER) em relação ao desempenho e ao plano de consulta.
A sintaxe JOIN explícita é mais clara e menos ambígua (veja os links abaixo)
Agora, o JOIN-before-WHERE é um processamento lógico , não um processamento real , e os otimizadores modernos são espertos o suficiente para realizar isso.
Seu problema aqui é provavelmente a indexação.
Por favor, mostre-nos todos os índices e chaves nessas tabelas. E os planos de consulta
Nota: essa questão já estaria próxima no StackOverflow por ser uma duplicata agora ... COUNT (1) vs COUNT (*) também é outro mito eliminado.
fonte
join
ewhere
cláusula. Otimizo as consultas de longa duração o tempo todo e, às vezes, a consulta usando awhere
cláusula tem melhor desempenho do que as que são usadasjoin
por um fator de até 70x. Se fosse assim tão simples e direta, a vida seria todos arco-íris e unicórnios. E não se trata de um antigo motor obscuro - agora eu estou olhando para 70x vantagem dewhere
cláusula no SQL 2012.where
consulta de cláusula é executada no lote grande do qual ele deve fazer parte, ela supera ajoin
consulta por uma margem enorme. As consultas SQL não são executadas no vácuo - elas são afetadas pelo restante da carga útil do servidor e, muitas vezes, aswhere
consultas da cláusula se saem muito bem, o que é um aborrecimento, pois ajoin
sintaxe é realmente muito mais limpa.Você deve refatorar completamente a consulta
Tente executar as cláusulas WHERE mais cedo e os JOINs depois
Mesmo se você executar um plano EXPLAIN nessa consulta refatorada e parecer pior que o original, tente mesmo assim. As tabelas temporárias criadas internamente executarão junções cartesianas, mas essas tabelas são menores para trabalhar.
Eu recebi essa ideia deste vídeo do YouTube .
Experimentei os princípios do vídeo em uma pergunta muito complexa no StackOverflow e recebi uma recompensa de 200 pontos.
@gbn mencionado, certificando-se de que você tenha os índices corretos. Nesse caso, indexe a coluna criada no MasterTable.
De uma chance !!!
UPDATE 2011-06-24 22:31 EDT
Você deve executar estas consultas:
Se NullRoles X 20 <AllRoles (em outras palavras, se NullRoles for menor que 5% das linhas da tabela), você deverá criar um índice não exclusivo da função na UserTable. Caso contrário, uma tabela completa da UserTable seria suficiente, pois o Query Optimizer pode possivelmente descartar o uso de um índice.
ATUALIZAÇÃO 25-06-2011 12:40 EDT
Como sou um DBA do MySQL, meu método de fazer as coisas requer não confiar no MySQL Query Optimizer através de pessimismo positivo e ser conservador. Assim, tentarei refatorar uma consulta ou criar índices de cobertura necessários para superar os maus hábitos ocultos do MySQL Query Optimizer. A resposta da @ gbn parece mais completa, pois o SQL Server pode ter mais "senso de humor" na avaliação de consultas.
fonte
Tínhamos uma tabela [Detalhe] com cerca de 75 milhões de linhas; uma tabela [Master] com cerca de 400 K linhas e uma tabela [Item] relacionada com 7 linhas - sempre e para sempre. Ele armazenava o pequeno conjunto de “Números de itens” (1-7) e modelava um formulário em papel, milhões dos quais eram impressos e distribuídos todos os meses. A consulta mais rápida foi a que você provavelmente menos pensou primeiro, envolvendo o uso de uma junção cartesiana. IIRC, era algo como:
Embora exista um vínculo lógico de "id" entre [Item] e [Detalhe], o CROSS JOIN funcionou melhor que o INNER JOIN.
O RDBMS foi o Teradata com sua tecnologia MPP e o IDR, como era o esquema de indexação. A tabela de 7 linhas não tinha índice, pois a TABLE SCAN sempre apresentava o melhor desempenho.
fonte