我有一个类似StackOverflow的标记系统,用于我正在处理的数据库.我正在编写一个存储过程,根据WHERE子句中未确定数量的标记查找结果.可以有0到10个标签之间的任何位置来过滤结果.例如,用户可能正在搜索标记为“apple”,“orange”和“banana”的项目,并且每个结果必须包含所有3个标记.我的查询变得更加复杂,因为我还在处理标记的交叉引用表,但出于这个问题的目的,我不会进入那个.
我知道我可以做一些字符串操作并向exec()函数提供一个查询来处理这个问题,但我宁愿不解决与动态sql相关的性能问题.我认为最好是sql缓存存储过程的查询计划.
在这种情况下,您使用了哪些技术来避免动态sql?
根据大众需求,这是我正在使用的查询:
SELECT ft.[RANK],s.shader_id,s.page_name,s.name,s.description,s.download_count,s.rating,s.price FROM shader s INNER JOIN FREETEXTTABLE(shader,*,@search_term) AS ft ON s.shader_id = ft.[KEY] WHERE EXISTS(SELECT tsx.shader_id FROM tag_shader_xref tsx INNER JOIN tag t ON tsx.tag_id = t.tag_id WHERE tsx.shader_id = s.shader_id AND t.tag_name = 'color') AND EXISTS(SELECT tsx.shader_id FROM tag_shader_xref tsx INNER JOIN tag t ON tsx.tag_id = t.tag_id WHERE tsx.shader_id = s.shader_id AND t.tag_name = 'saturation') ORDER BY ft.[RANK] DESC
解决方法
有关此问题以及类似问题的详细概述,请参阅:
http://www.sommarskog.se/dyn-search-2005.html
具体到你的问题是这里的部分:http://www.sommarskog.se/dyn-search-2005.html#AND_ISNOTNULL
还要考虑到(直接)动态解决方案不一定比(可能是复杂的)静态解决方案慢,因为查询计划仍然可以缓存:请参阅http://www.sommarskog.se/dyn-search-2005.html#dynsql
因此,您必须根据实际数据量仔细测试/衡量您的选项,同时考虑实际查询(例如,使用一个或两个参数进行搜索可能比使用十个搜索更常见,等等)
编辑:提问者给出了一个很好的理由在评论中对此进行优化,从而将“过早”警告移开:
然而,(标准;)警告词适用:这很像过早优化! – 你确定这个sproc会被调用,通常情况下使用动态sql会明显变慢(也就是说,与应用程序中正在进行的其他事情相比)?