除了表名外,我有 10 个具有相同结构的表。
我有一个 sp(存储过程)定义如下:
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)
我用以下行调用 sp:
call mySP('test') //it executes in 6,836s
然后我打开了一个新的标准查询窗口。我刚刚复制了上面的查询。然后将@param1 替换为“测试”。
这在 0,321 秒内执行,比存储过程快约 20 倍。
我反复更改参数值以防止结果被缓存。但这并没有改变结果。SP 比同等标准查询慢约 20 倍。
请你能帮我弄清楚为什么会这样吗?
有没有人遇到过类似的问题?
我在 windows server 2008 R2 64 位上使用 mySQL 5.0.51。
编辑:我正在使用 Navicat 进行测试。
任何想法都会对我有所帮助。
编辑1:
我刚刚根据 Barmar 的回答做了一些测试。
最后,我将 sp 更改为如下所示的一行:
SELECT * FROM table1 WHERE col1=@param1 AND col2=@param2
然后首先我执行了标准查询
SELECT * FROM table1 WHERE col1='test' AND col2='test' //Executed in 0.020s
在我打电话给我的 sp 之后:
CALL MySp('test','test') //Executed in 0.466s
所以我完全改变了where子句,但没有任何改变。我从mysql命令窗口而不是navicat调用了sp。它给出了相同的结果。我仍然坚持下去。
我的 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 被组合索引。
你可以说那你为什么不使用标准查询呢?我的软件设计不适合这个。我必须使用存储过程。所以这个问题对我来说非常重要。
编辑2:
我得到了查询配置文件信息。很大的不同是因为 SP Profile Information 中的“发送数据行”。发送数据部分需要 %99 的查询执行时间。我正在本地数据库服务器上进行测试。我没有从远程计算机连接。
SP 配置文件信息
查询档案信息
我在我的 sp 中尝试了如下所示的 force index 语句。但同样的结果。
SELECT * FROM table1 FORCE INDEX (col1_col2_combined_index) WHERE col1=@param1 AND col2=@param2
我已经改变了 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
我在 SP 中使用 FORCE INDEX 语句。但它坚持不使用索引。任何的想法?我想我快结束了:)