procedimento armazenado mysql é mais lento 20 vezes do que a consulta padrão
Eu tenho 10 tabelas com a mesma estrutura, exceto o nome da tabela.
Eu tenho um sp (procedimento armazenado) definido da seguinte forma:
select * from table1 where (@param1 IS NULL OR col1=@param1)
UNION ALL
select * from table2 where (@param1 IS NULL OR col1=@param1)
UNION ALL
...
...
UNION ALL
select * from table10 where (@param1 IS NULL OR col1=@param1)
Eu estou chamando o sp com a seguinte linha:
call mySP('test') //it executes in 6,836s
Então eu abri uma nova janela de consulta padrão. Acabei de copiar a consulta acima. Em seguida, substituiu @ param1 por 'test'.
Isso executado em 0,321s e é cerca de 20 vezes mais rápido que o procedimento armazenado.
Eu alterei o valor do parâmetro repetidamente para evitar que o resultado seja armazenado em cache. Mas isso não mudou o resultado. O SP é cerca de 20 vezes mais lento que a consulta padrão equivalente.
Por favor, você pode me ajudar a descobrir por que isso está acontecendo?
Alguém encontrou problemas semelhantes?
Eu estou usando o mySQL 5.0.51 no windows server 2008 R2 64 bit.
edit: Estou usando o Navicat para teste.
Qualquer ideia será útil para mim.
EDIT1:
Acabei de fazer alguns testes de acordo com a resposta de Barmar.
Finalmente eu mudei o sp como abaixo com apenas uma linha:
SELECT * FROM table1 WHERE col1=@param1 AND col2=@param2
Então, em primeiro lugar eu executei a consulta standart
SELECT * FROM table1 WHERE col1='test' AND col2='test' //Executed in 0.020s
Depois liguei para o meu sp:
CALL MySp('test','test') //Executed in 0.466s
Então eu mudei a cláusula where inteiramente, mas nada mudou. E eu chamei o sp da janela de comando do mysql em vez do navicat. Deu o mesmo resultado. Eu ainda estou preso nisso.
meu sp ddl:
CREATE DEFINER = `myDbName`@`%`
PROCEDURE `MySP` (param1 VARCHAR(100), param2 VARCHAR(100))
BEGIN
SELECT * FROM table1 WHERE col1=param1 AND col2=param2
END
E col1 e col2 são combinados indexados.
Você poderia dizer que por que você não usa a consulta standart então? Meu design de software não é adequado para isso. Eu devo usar o procedimento armazenado. Então esse problema é muito importante para mim.
EDIT2:
Eu obtive informações de perfil de consulta. A grande diferença é por causa do "envio de linha de dados" em Informações do Perfil do SP. O envio de parte de dados leva 99% do tempo de execução da consulta. Eu estou fazendo teste no servidor de banco de dados local. Eu não estou conectando do computador remoto.
Informações de perfil SP
Informações de perfil de consulta
Eu tentei declaração de índice de força como abaixo no meu sp. Mas mesmo resultado.
SELECT * FROM table1 FORCE INDEX (col1_col2_combined_index) WHERE col1=@param1 AND col2=@param2
Eu mudei sp como abaixo.
EXPLAIN SELECT * FROM table1 FORCE INDEX (col1_col2_combined_index) WHERE col1=param1 AND col2=param2
Isso deu esse resultado:
id:1
select_type=SIMPLE
table:table1
type=ref
possible_keys:NULL
key:NULL
key_len:NULL
ref:NULL
rows:292004
Extra:Using where
Então eu executei a consulta abaixo.
EXPLAIN SELECT * FROM table1 WHERE col1='test' AND col2='test'
Resultado é:
id:1
select_type=SIMPLE
table:table1
type=ref
possible_keys:col1_co2_combined_index
key:col1_co2_combined_index
key_len:76
ref:const,const
rows:292004
Extra:Using where
Eu estou usando a instrução FORCE INDEX no SP. Mas insiste em não usar o índice. Qualquer ideia? Eu acho que estou perto do fim :)