【发布时间】:2013-05-25 18:58:34
【问题描述】:
我有 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 替换为'test'。
这在 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 被合并索引。
你可以说那你为什么不使用标准查询呢?我的软件设计不适合这个。我必须使用存储过程。所以这个问题对我来说非常重要。
EDIT2:
我已获得查询个人资料信息。很大的不同是因为 SP Profile Information 中的“发送数据行”。发送数据部分需要 %99 的查询执行时间。我正在本地数据库服务器上进行测试。我没有从远程计算机连接。
SP 个人资料信息
查询个人资料信息
我已经在我的 sp 中尝试了如下所示的强制索引语句。但结果相同。
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 语句。但它坚持不使用索引。任何的想法?我想我快结束了:)
【问题讨论】:
-
可能是执行SP后,MySQL已经缓存了结果,然后在SP外执行时,只是命中缓存而不是再次执行。
-
对了,为什么10个表结构一样?为什么不将它们合并到一张表中?
-
数据库设计超出了我的掌控,我永远不会做这样的设计:) 首先我使用不同的参数执行查询,然后立即使用相同的参数调用 sp。结果相同。似乎 sp 甚至没有从缓存中获取结果。
-
当您将其作为普通查询执行时,您是否将每个子查询上出现的@param1 都替换为“test”,或者只使用 (col1 = 'test')。如果是这样怀疑mysql可能由于OR而无法在存储过程中使用索引,但在查询中使用了一个
-
带有
FORCE INDEX的SP 工作得更快吗?查询优化器可能不如其他数据库那么好,并创建计划 before 用它们的值替换参数