Procedura przechowywana mysql jest wolniejsza 20 razy niż standardowe zapytanie
Mam 10 stołów o tej samej strukturze z wyjątkiem nazwy tabeli.
Mam sp (procedurę przechowywaną) zdefiniowaną następująco:
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)
Nazywam sp z następującej linii:
call mySP('test') //it executes in 6,836s
Następnie otworzyłem nowe standardowe okno zapytania. Właśnie skopiowałem powyższe zapytanie. Następnie zastąpiono @ param1 słowem „test”.
Wykonano to w 0,321s i jest około 20 razy szybsze niż procedura składowana.
Wielokrotnie zmieniłem wartość parametru, aby zapobiec buforowaniu wyniku. Ale to nie zmieniło wyniku. SP jest około 20 razy wolniejsza niż równoważne standardowe zapytanie.
Czy możesz mi pomóc dowiedzieć się, dlaczego tak się dzieje?
Czy ktoś napotkał podobne problemy?
Używam mySQL 5.0.51 na Windows Server 2008 R2 64-bit.
edit: używam Navicat do testowania.
Każdy pomysł będzie dla mnie pomocny.
EDIT1:
Po prostu wykonałem test zgodnie z odpowiedzią Barmara.
W końcu zmieniłem sp jak poniżej z jednym tylko jednym wierszem:
SELECT * FROM table1 WHERE col1=@param1 AND col2=@param2
Następnie najpierw wykonałem zapytanie standartowe
SELECT * FROM table1 WHERE col1='test' AND col2='test' //Executed in 0.020s
Po wywołaniu my sp:
CALL MySp('test','test') //Executed in 0.466s
Zmieniłem więc całkowicie klauzulę, ale nic się nie zmieniło. I wywołałem sp z okna poleceń mysql zamiast navicat. Dało to taki sam rezultat. Nadal na tym utknąłem.
mój spddl:
CREATE DEFINER = `myDbName`@`%`
PROCEDURE `MySP` (param1 VARCHAR(100), param2 VARCHAR(100))
BEGIN
SELECT * FROM table1 WHERE col1=param1 AND col2=param2
END
A col1 i col2 są połączone indeksowane.
Można powiedzieć, że dlaczego nie używasz wtedy standardowego zapytania? Mój projekt oprogramowania nie jest do tego odpowiedni. Muszę użyć procedury przechowywanej. Więc ten problem jest dla mnie bardzo ważny.
EDIT2:
Otrzymałem informacje o profilu zapytania. Duża różnica polega na „wysyłaniu wiersza danych” w informacji profilu SP. Część danych wysyłanych zajmuje% 99 czasu wykonania zapytania. Robię test na lokalnym serwerze bazy danych. Nie łączę się z komputerem zdalnym.
Informacje profilu SP
Informacje o profilu zapytania
Próbowałem wymusić wypowiedź indeksu jak poniżej w moim sp. Ale ten sam wynik.
SELECT * FROM table1 FORCE INDEX (col1_col2_combined_index) WHERE col1=@param1 AND col2=@param2
Zmieniłem sp jak poniżej.
EXPLAIN SELECT * FROM table1 FORCE INDEX (col1_col2_combined_index) WHERE col1=param1 AND col2=param2
Dało to ten wynik:
id:1
select_type=SIMPLE
table:table1
type=ref
possible_keys:NULL
key:NULL
key_len:NULL
ref:NULL
rows:292004
Extra:Using where
Następnie wykonałem zapytanie poniżej.
EXPLAIN SELECT * FROM table1 WHERE col1='test' AND col2='test'
Wynik:
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
Używam instrukcji FORCE INDEX w SP. Ale nalega na nieużywanie indeksu. Dowolny pomysł? Myślę, że jestem blisko końca :)