Pergunta

Em primeiro lugar, esta pergunta diz respeito MySQL 3.23.58, portanto, é aconselhável.

Eu tenho 2 tabelas com a seguinte definição:

Table A: id INT (primary), customer_id INT, offlineid INT

Table B: id INT (primary), name VARCHAR(255)

Agora, a tabela A contém na faixa de 65k registros +, enquanto a tabela B contém ~ 40 registros. Além dos 2 índices de chave primária, há também um índice na offlineid campo na tabela A. Há mais campos em cada mesa, mas eles não são relevantes (como eu vê-lo, perguntar se necessário) para esta consulta.

I foi apresentado pela primeira vez com a seguinte consulta ( tempo de consulta: ~ 22 segundos ):

SELECT b.name, COUNT(*) AS orders, COUNT(DISTINCT(a.kundeid)) AS leads
FROM katalogbestilling_katalog a, medie b
WHERE a.offlineid = b.id
GROUP BY b.name

Agora, cada id em medie está associada com um nome diferente, o que significa que você poderia grupo por id, bem como nome. Um pouco de testar e para trás me povoada este ( tempo de consulta: ~ 6 segundos ):

SELECT a.name, COUNT(*) AS orders, COUNT(DISTINCT(b.kundeid)) AS leads
FROM medie a
INNER JOIN katalogbestilling_katalog b ON a.id = b.offline
GROUP BY b.offline;

Existe alguma maneira de pôr em marcha-lo para baixo a tempo "instantâneo" (1 segundo máx na pior das hipóteses)? Eu adicionei o índice em offlineid, mas além disso e o re-arranjo da consulta, eu estou em uma perda para o que fazer. A EXPLICAR consulta mostra-me a consulta está usando fileshort (a consulta original também usou tabelas temporárias). Todas as sugestões são bem-vindos!

Foi útil?

Solução

Você pode tentar fazer índices certeza de que há cobertura definidos em cada mesa. Um índice de cobertura é apenas um índice em que cada coluna solicitada no seleccione ou utilizado em uma associação está incluído no índice. Desta forma, o motor só tem que ler a entrada de índice e não precisa também fazer o lookup linha correspondente para obter quaisquer colunas solicitadas não incluídos no índice. Eu usei esta técnica com grande sucesso em Oracle e MS SQLServer.

Olhando para a sua consulta, você pode tentar:

um índice para medie.id, medie.name
um índice para katalogbestilling_katalog.offlineid, katalogbestilling_katalog.kundeid

As colunas devem ser definidos nestas encomendas para o índice. Isso faz uma diferença se o índice pode ser usado ou não.

Mais informações aqui:

Covering Índice Informações

Outras dicas

Estou indo para adivinhar que o seu principal problema é que você está usando uma versão tão antiga do MySQL. Talvez MySQL 3 não gosta do COUNT (DISTINCT ()).

Como alternativa, que poderia ser apenas o desempenho do sistema. Quanta memória você tem?

Ainda assim, MySQL 3 é realmente velho. Eu, pelo menos, montar um sistema de teste para ver se uma versão mais recente correu que consulta mais rápida.

Infelizmente, mysql 3 não suporta sub-consultas. Eu suspeito que a versão antiga, em geral, é o que está fazendo com que o desempenho lento.

Você pode obter um pequeno aumento no desempenho se você remover a junção interna e substituí-lo com uma instrução SELECT aninhada também remover a contagem (*) e substituí-lo com o PK.

SELECT a.name, COUNT(*) AS orders, COUNT(DISTINCT(b.kundeid)) AS leads FROM medie aINNER JOIN katalogbestilling_katalog b ON a.id = b.offline GROUP BY b.offline;

seria

SELECT a.name, COUNT(a.id) AS orders, (SELECT COUNT(kundeid) FROM katalogbestilling_katalog b WHERE b.offline = a.id) AS Leads FROM medie a;

Bem, se a consulta é executada com frequência suficiente para justificar a sobrecarga, criar um índice na tabela A contendo os campos usados ??na consulta. Então, todos os resultados podem ser lidos a partir de um índice e que costuma ter para fazer a varredura da tabela.

Dito isso, toda a minha experiência é baseada em MSSQL, por isso pode não funcionar.

Sua segunda consulta é fino e 65k + 40k linhas não é muito grande:)

Coloque um índice novo em coluna katalogbestilling_katalog.offline e ele vai correr mais rápido para você.

Como é kundeid definido? Seria útil para ver o esquema completo para ambas as tabelas (como gerado pelo MySQL, ie., Com índices), bem como a saída de explicar com a consultas acima.

A maneira mais fácil de depurar este e descobrir o que é o gargalo seria para começar a remover campos, um por um, a partir da consulta e medir quanto tempo leva para executar (lembre-se de executar RESTABELECER CONSULTA CACHE antes de executar cada consulta ). Em algum momento você vai ver uma queda significativa no tempo de execução e, em seguida, você já identificou o gargalo. Por exemplo:

SELECT b.name, COUNT(*) AS orders, COUNT(DISTINCT(a.kundeid)) AS leads
FROM katalogbestilling_katalog a, medie b
WHERE a.offlineid = b.id
GROUP BY b.name

pode tornar-se

SELECT b.name, COUNT(DISTINCT(a.kundeid)) AS leads
FROM katalogbestilling_katalog a, medie b
WHERE a.offlineid = b.id
GROUP BY b.name

para eliminar a possibilidade de "ordens" sendo o gargalo, ou

SELECT b.name, COUNT(*) AS orders
FROM katalogbestilling_katalog a, medie b
WHERE a.offlineid = b.id
GROUP BY b.name

para eliminar "leva" da equasion. Isso vai levar você na direção certa.

Atualização : Eu não estou sugerindo remover qualquer um dos dados da consulta final. Apenas removê-los para reduzir o número de variáveis ??ao olhar para o gargalo. Dado o seu comentário, eu entendo

SELECT b.name
FROM katalogbestilling_katalog a, medie b
WHERE a.offlineid = b.id
GROUP BY b.name

ainda está realizando mal? Isto significa claramente que é tanto a juntar-se que não é otimizado ou o grupo, (que você pode testar por remoção do grupo por - tanto o JOIN será ainda lento, caso em que esse é o problema que você precisa para correção, ou não vai - caso em que ele é, obviamente, o GROUP BY). Você pode postar a saída do

EXPLAIN SELECT b.name
FROM katalogbestilling_katalog a, medie b
WHERE a.offlineid = b.id
GROUP BY b.name

, bem como os esquemas de tabela (para torná-lo mais fácil de depurar)?

update # 2

Há também uma possibilidade de que todos os seus indeces são criados corretamente, mas você tem que você instalação mysql mal configurado quando se trata de uso de memória max ou algo nesse sentido que obriga a usar triagem disco.

Tente adicionar um índice para (offlineid, kundeid)

Eu adicionei 180.000 linhas BS para katalog e 30.000 BS linhas para medie (com katalog offlineid do correspondente a medie id de e com certeza a contagem de trabalho disinct uma sobreposição alguns de fazer kundeid). Mente-lhe este está em mysql 5, por isso, se você não tem resultados semelhantes, mysql 3 pode ser o seu culpado, mas pelo que me lembro mysql 3 deve ser capaz de lidar com isso muito bem.

As minhas tabelas:

CREATE TABLE `katalogbestilling_katalog` (
  `id` int(11) NOT NULL auto_increment,
  `offlineid` int(11) NOT NULL,
  `kundeid` int(11) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `offline_id` (`offlineid`,`kundeid`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=60001 ;

CREATE TABLE `medie` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=30001 ;

A minha consulta:

SELECT b.name, COUNT(*) AS orders, COUNT(DISTINCT(a.kundeid)) AS leads
FROM medie b
INNER JOIN katalogbestilling_katalog a ON b.id = a.offlineid
GROUP BY a.offlineid
LIMIT 0 , 30


"Showing rows 0 - 29 (30,000 total, Query took 0.0018 sec)"

E a explicar:

id:  1
select_type:    SIMPLE
table: a
type: index
possible_keys:  NULL
key:    offline_id
key_len:    8
ref: NULL
rows: 180000
Extra: Using index

id: 1
select_type:    SIMPLE
table: b
type: eq_ref
possible_keys:  PRIMARY
key:    PRIMARY
key_len:    4
ref: test.a.offlineid
rows: 1
Extra:

Tente otimizar o próprio servidor. Veja este post por Peter Zaitsev para as variáveis ??mais importantes. Alguns são InnoDB específico, enquanto outros são para MyISAM. Voc no mencionar qual o motor que você estava usando o que pode ser relevante neste caso (count (*) é muito mais rápido em MyISAM que no InnoDB por exemplo). Aqui está outro post do blog mesmo , e um artigo de MySQL Forge

Quanto tempo dura esta tomada:

SELECT fieldlist FROM A
SELECT fieldlist FROM B

Se o seu mysql está funcionando assim lento sobre a juntar-se, talvez seja melhor para obter os dados com varreduras de tabela individuais e costurar os dados em conjunto fora do db. 65k registros realmente não é que muitos.

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