我们的软件部署在他们遇到性能问题的客户端站点上,他们聘请了一名SQL顾问来查看数据库并查看他们的瓶颈所在。
顾问发现的一件事是我们很多陈述转换为nvarchar
的陈述。
经过一番调查后,我发现是PreparedStatement
正在进行调查。
举个例子:
PreparedStatement query = connection.prepareStatement("SELECT * FROM sys.tables WHERE"
+ " name LIKE ?");
query.setString(1, "%%");
成为
declare @p1 int
set @p1=1
exec sp_prepexec @p1 output,N'@P0 nvarchar(4000)',N'SELECT * FROM sys.tables WHERE name LIKE @P0 ',N'%%'
select @p1
另一方面,adhoc executeQuery方法只是通过发送SQL
ResultSet rs = connection.createStatement().executeQuery("SELECT * FROM sys.tables WHERE name LIKE '%%'");
变为
SELECT * FROM sys.tables WHERE name LIKE '%%'
我想要解决的是这实际上有多糟糕。准备语句在我们的应用程序中使用,因为它们的使用应该比adhoc查询更有效(如果执行多次)。
此外,我无法看到微软的人会在他们知道会导致性能问题的驱动程序中加入一些内容。
这是我们应该真正研究的问题,还是咨询顾问在没有问题时寻找问题?
答案 0 :(得分:1)
pepared语句强制查询成为参数化查询(这是一件好事),而ad-hoc查询可能会也可能不会被SQL引擎自动参数化。简而言之,它并不是一个重大的性能影响。
但是,从设计的角度来看,是否应该使用参数化存储过程总是存在很多争论(不一定是表演存储过程)。我认为大多数DBA(可能还有数据库顾问)更喜欢存储过程,因为它们使用传统的数据库管理工具(以及提供安全性优势,默认情况下包括参数化)更容易调试。
答案 1 :(得分:0)
准备语句带有比ad-hoc查询更多的优化选项,从安全角度来看通常会更好(没有设计的SQL注入)。
nvarchar 用法通常来自非功能性要求。如果您希望您的应用程序支持任何现在非常常见的Unicode字符,那么您需要它。如果符合要求,请不要更改。
我认为 LIKE 查询是罪魁祸首,您应该在后端数据库中查看全文索引功能。 查询看起来非常简单,它是LIKE'%'查询导致扫描每个字段中的字符序列。