存储过程中动态游标的性能

时间:2014-04-18 22:23:00

标签: mysql sql performance stored-procedures

我想知道当你有一个select查询可以在传递给存储过程的where子句中包含多个(20+)参数的任意组合时,获得更好性能的最佳实践是什么。

假设我有一个查询应该返回人员及其地址列表(每人可能超过1个地址)。用户想要通过人/地址表中的任何可能的字段组合进行搜索。搜索可以在一个字段上,也可以在所有20个字段或其间的任何字段上进行搜索。

我用来处理这个问题的方法是创建一个这样的游标 (为简单起见,我列出了2个变量,只有varchar和int)

create procedure dynasp for (
in in_name varchar(40),
in in_age int 
 ..... rest of parameters here...


declare cursor cs for 
   select .... from person join address.... 
   where
    (in_age = 0 or in_age = person_age) and 
    (in_name is null or rtrim(in_name)='' or in_name = person.name)
    and...

我相信因为输入变量的值是常量,所以查询不应该在每一行上对它进行评估或者是这样吗?

我使用的另一个选项是使用sp中的字符串构建的动态游标。这样它只包含where子句中不为空的字段,但我相信这意味着需要在每次调用SP时构造和重新编译sql。

我的问题是针对最佳做法,建议采用上述哪种方法,还有比上述2种方法更好的方法吗?

谢谢

2 个答案:

答案 0 :(得分:0)

这取决于您要搜索的表格的大小。如果where子句中有20多个条件,都包含or个运算符,则查询优化器将无法选择要使用的良好索引,并且可能只扫描整个表。对于小型表,这无关紧要,但对于非常大的表,它会很慢。

构建动态查询的另一种选择是在解析和选择查询计划时会产生一些开销,但是在执行时,查询可能会更有效。 (确保您正在防范SQL注入漏洞)。

所以最好的做法是对两者进行基准测试,看看你的情况最好。

答案 1 :(得分:0)

性能问题基本上取决于一件简单的事情:您的表是否有任何您打算用来提高查询性能的索引?

如果索引不是问题,那么您的方法很好。好吧,让我补充一下:假设您正在进行的其他处理需要游标。如果您可以返回结果集并执行基于集合的处理,那么优于使用游标。

如果索引是个问题,那么带有一堆常量表达式的长复杂where语句可能会混淆MySQL编译器。有关使用where子句索引的文档是here。 MySQL肯定会删除常量表达式。但是,在一个非常复杂的表达式中,我不确定这与选择正确的索引有多好。 (我假设您正在使用基于语法的MySQL)。

对于后一种情况,动态游标将是有益的,因为它会鼓励MySQL选择使用索引的执行计划。

因此,如果您没有使用索引(或分区),那么您当前的方法就可以了。如果是,请查看查询的执行计划。如果他们使用适当的索引,那么您当前的方法就可以了。如果不是,请考虑使用动态游标。