Depois de receber a resposta para Como posso obter um contador de classificação válido? , adaptei ao meu próprio sistema. Mas agora, eu tenho um problema de desempenho. Todas as minhas solicitações são muito rápidas (menos de 0,0005s para a maioria delas), mas ao usar ROW_NUMBER()
com vários esquemas, demora mais de 0,2s.
Aqui está um exemplo completo:
Esquema 1 , nomeado sanctions
, com uma tabela nomeada bans
e composta por:
id
, campo de incremento automáticouuid
, varchar com índice- outros conteúdos não vinculados à pergunta
Esta tabela atual tem mais de 400 linhas.
Esquema 2 , denominado stats
, com uma tabela nomeada players
e composta por:
id
, campo de incremento automáticouuid
, varchar com índicecoins
, dobro- outros conteúdos não vinculados à pergunta
Esta tabela atual tem mais de 2000 linhas.
Minha consulta completa é assim :
SELECT
uuid,
(SELECT count(*) FROM sanctions.bans WHERE uuid = p.uuid) as nb,
row_number() OVER (order by coins DESC) counter
FROM stats.players p;
Demora cerca de 0,22s.
Agora, vamos verificar parte por parte :
Ao executar SELECT count(*) FROM arkbans.litebans_bans WHERE uuid = p.uuid
(e substituindo p.uuid
por um valor), nunca vou além de 0,0002s.
Ao executar:
SELECT
uuid,
row_number() OVER (order by coins DESC) counter
FROM stats.players p;
Demora cerca de 0,0017s.
Com ANALYZE
chave:
Com ANALYZE FORMAT=JSON
: aqui
Consulta analisada:
WITH Bans AS
(
SELECT uuid, COUNT(*) AS BanCount
FROM sanctions.bans
GROUP BY uuid
)
SELECT
p.uuid,
COUNT(b.BanCount) as nb,
row_number() OVER (order by MAX(p.coins) DESC) counter
FROM stats.players p
LEFT JOIN Bans b ON p.uuid = b.uuid
Como posso corrigir esse problema de desempenho?
Nota: a coluna "moedas" aqui é um exemplo. Na realidade, mais de 60 colunas usarão essa solicitação. Portanto, adicionar índice para cada coluna como esta não é uma opção para mim (muitos índices, com valores muito diferentes)
Nota 2: Não é possível fazer um db fiddle, pois está em vários bancos de dados e com muitos dados, desculpe.
Sim, executá-lo para um único
uuid
é de apenas 0,0002s, mas quantas linhas /uuid
s existem na suastats.players
tabela? E se você multiplicar essa contagem por 0,0002s, quanto tempo dura o tempo de execução total agora? Isso é efetivamente o que você está fazendo quando tem uma expressão embutida em suaSELECT
lista que filtra uma determinada linha da tabela externa. (Não é exatamente a mesma coisa, mas perto o suficiente para você ter uma ideia.)Você deve escrever sua consulta de uma forma mais relacional, com um real
JOIN
, assim:Você pode achar esta reescrita ainda mais eficaz, juntando diretamente e agrupando os resultados:
Conforme mencionado nos comentários, um índice na
(uuid, coins)
tabelastats.players
pode ser mais adequado para o seu tipo de consulta.Você
ANALYZE FORMAT=JSON
está mostrando que a maior parte do tempo é gasto emsanctions.bans
. Especificamente esta linha é interessante:Isso
convert(b.uuid using utf8mb4)
me indica que suauuid
coluna nasanctions.bans
tabela é um conjunto de caracteres diferente daquele dastats.players
tabela. Isso é chamado de conversão implícita e pode causar problemas de desempenho. Intuitivamente, sinto que esse é o seu gargalo. Verifique e certifique-se de que ambos os campos são os mesmos conjuntos de caracteres (e agrupamentos).