【问题标题】:Efficient way of running lots of Dynamic SQL运行大量动态 SQL 的有效方法
【发布时间】:2014-05-19 20:10:14
【问题描述】:

总结

有没有一种有效的方法来运行大量的动态 SQL(在 SQL Server 2005 上)?

详情

我们的系统允许用户创建“电子邮件提醒”订阅 - 系统上的新匹配项每天都会通过电子邮件发送给他们。

订阅允许多种选择,包括使用搜索关键字。我自己编写的解析器输出适当的 SQL 代码,同时考虑到andor 和括号()解析器不允许任何可用于 SQL 注入的东西。

例如,用户输入的关键字可能为this (that or other),结果查询结果大致为...

SELECT *
FROM [VW_EMAIL_ALERT]
WHERE ([SEARCH] LIKE '%this%' AND ([SEARCH] LIKE '%that%' OR [SEARCH] LIKE '%other%'))

每晚,所有这些订阅都会单独处理,因为每个订阅都可能是独一无二的。结果是批处理必须在每个订阅上运行一个游标,并通过sp_executesql 运行 SQL。

显然这是非常低效的,并且可能导致严重的过载 - 在某些情况下会导致超时。运行此处理的存储过程被编码为将订阅拆分为块,因此它们不会被一次全部调用。

有没有更好/更有效的方法来做到这一点?

注意:不幸的是,我们目前至少支持 SQL Server 2005,因为我们的一些客户仍在使用该技术

【问题讨论】:

  • 也许是一个愚蠢的问题,但您不能将其更改为使用静态 SQL 吗? (是的,我知道要更改您的架构可能需要付出很多努力)。顺便说一句,您使用的是“纯”动态还是参数动态?
  • 您知道 % 不是带 = 的通配符吗?正如所写, where 永远不可能是真的。
  • 这可能会有所帮助:stackoverflow.com/questions/13259850/…
  • 谢谢@Blam,对不起——那只是我为这个问题写了一个例子——你是完全正确的......我会编辑
  • 参数化动态 sql(使用 sp_executesql)在性能方面没有任何问题。您可以通过并行化尽可能多的工作来加快速度。

标签: sql sql-server tsql sql-server-2005 dynamic-sql


【解决方案1】:

如果您正在寻找效率最低的关键字
一个like '%anything 不使用索引

使用全文搜索来索引单词

或者编写自己的解析器来索引唯一词
您将建立一个关键字表
并索引关键字
这是一个非常有效的查询

select id 
  from keywords 
 where keyword = 'this' 
intersect 
select id 
  from keywords 
 where keyword in ( 'that','other')

即使在关键字中使用通配符,它​​仍然比搜索整个文本更有效

【讨论】:

  • 谢谢 Blam,我认为您是对的,全文搜索非常适合这种情况 - 不幸的是,我们的所有客户端服务器上都没有全文可用。
  • 然后自己写。只需将文本解析为关键字表即可。
  • 这不是一个坏主意@Blam,我真的很喜欢 :-) 谢谢! (编辑:啊,但不幸的是它无法处理andor 或括号。该死)
  • 为什么不呢?我给了你一个和或的例子。
  • 没错,但是说(有点极端),用户决定输入像this and (that or (other and something)) and else 这样的东西,那怎么能做到呢?
【解决方案2】:

我希望这会有所帮助。在我的工作中,我们用这种实现替换了 cursor。

DECLARE
    @strSQL NVARCHAR(MAX) = ''

CREATE TABLE #tmp
(
    Result_Query VARCHAR(MAX)
)

INSERT INTO
    #tmp
SELECT
    'SELECT * FROM [VW_EMAIL_ALERT] WHERE ([SEARCH] = ''%this%'' AND ([SEARCH] = ''%that%'' OR [SEARCH] = ''%other%''))'

UNION

SELECT
    'SELECT * FROM [VW_EMAIL_ALERT] WHERE ([SEARCH] = ''%this1%'' AND ([SEARCH] = ''%that1%'' OR [SEARCH] = ''%other1%''))'

SELECT
    @strSQL = @strSQL + Result_Query + ';'
FROM
    #tmp

SET
    @strSQL = LEFT(@strSQL, LEN(@strSQL) - 1)

PRINT @strSQL
EXEC(@strSQL)

【讨论】:

  • 感谢您的建议,但老实说,我真的看不出这样会更有效率。
猜你喜欢
  • 1970-01-01
  • 2022-01-13
  • 2016-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多