У меня есть 10 таблиц с одинаковой структурой, кроме имени таблицы.
У меня есть sp (хранимая процедура), определяемая следующим образом:
select * from table1 where (@param1 IS NULL OR [email protected])
UNION ALL
select * from table2 where (@param1 IS NULL OR [email protected])
UNION ALL
...
...
UNION ALL
select * from table10 where (@param1 IS NULL OR [email protected])
Я вызываю sp со следующей строкой:
call mySP('test') //it executes in 6,836s
Затем я открыл новое стандартное окно запросов. Я просто скопировал запрос выше. Затем замените @param1 на "test".
Это выполняется в 0,321 с и примерно в 20 раз быстрее, чем хранимая процедура.
Я неоднократно менял значение параметра для предотвращения кэширования результата. Но это не изменило результат. SP примерно в 20 раз медленнее, чем эквивалентный стандартный запрос.
Пожалуйста, помогите мне разобраться, почему это происходит?
Кто-нибудь сталкивался с подобными проблемами?
Я использую mySQL 5.0.51 на Windows Server 2008 R2 64 бит.
edit: Я использую Navicat для тестирования.
Любая идея будет полезна для меня.
EDIT1:
Я только что сделал тест в соответствии с ответом Бармара.
Наконец, я изменил sp, как показано ниже, только с одной строкой:
SELECT * FROM table1 WHERE [email protected] AND [email protected]
Затем, во-первых, я выполнил стандартный запрос
SELECT * FROM table1 WHERE col1='test' AND col2='test' //Executed in 0.020s
После того, как я вызвал my sp:
CALL MySp('test','test') //Executed in 0.466s
Итак, я полностью изменил предложение, но ничего не изменилось. И я вызвал sp из командного окна mysql вместо navicat. Это дало тот же результат. Я все еще придерживаюсь этого.
my sp ddl:
CREATE DEFINER = `myDbName`@`%`
PROCEDURE `MySP` (param1 VARCHAR(100), param2 VARCHAR(100))
BEGIN
SELECT * FROM table1 WHERE col1=param1 AND col2=param2
END
И col1 и col2 объединяются с индексом.
Можно сказать, почему вы не используете стандартный запрос? Мой дизайн программного обеспечения не подходит для этого. Я должен использовать хранимую процедуру. Поэтому эта проблема очень важна для меня.
EDIT2:
Я получил информацию о профиле запроса. Большая разница связана с "отправкой строки данных" в профильной информации SP. Отправка части данных занимает% 99 времени выполнения запроса. Я делаю тест на локальном сервере базы данных. Я не подключаюсь к удаленному компьютеру.
Информация о профиле SP
Информация о профиле запроса
Я попробовал инструкцию индекса силы, как показано ниже в моей sp. Но такой же результат.
SELECT * FROM table1 FORCE INDEX (col1_col2_combined_index) WHERE [email protected] AND [email protected]
Я изменил sp, как показано ниже.
EXPLAIN SELECT * FROM table1 FORCE INDEX (col1_col2_combined_index) WHERE col1=param1 AND col2=param2
Это дало такой результат:
id:1
select_type=SIMPLE
table:table1
type=ref
possible_keys:NULL
key:NULL
key_len:NULL
ref:NULL
rows:292004
Extra:Using where
Затем я выполнил запрос ниже.
EXPLAIN SELECT * FROM table1 WHERE col1='test' AND col2='test'
Результат:
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
Я использую оператор FORCE INDEX в SP. Но он настаивает на том, чтобы не использовать индекс. Есть идеи? Я думаю, что я близок к концу:)