使用activerecord_sqlserver_adapter我遇到了Rails activerecord对象的性能问题。这是生成的sql看起来很像并且运行速度非常慢;
EXEC sp_executesql N'SELECT COUNT(*) FROM [constituents] WHERE [constituents].[constituent_id] IN (N''10016125'', N''483663'', N''530657'', N''535217'')'
以下运行非常快;
EXEC sp_executesql N'SELECT COUNT(*) FROM [constituents] WHERE [constituents].[constituent_id] IN (''10016125'', ''483663'', ''530657'', ''535217'')'
适配器将N放在where子句中的每个项目前面,这会减慢速度。执行计划建议我添加一个索引,但这似乎是不必要的,这是一个遗留数据库。
有没有人建议我如何加快速度?
答案 0 :(得分:3)
我强烈建议您阅读How Data Access Code Affects Database Performance和Slow in the Application, Fast in SSMS? Understanding Performance Mysteries。这两篇文章都非常详细地介绍了这个主题。
摘要是Data Type Precedence的规则规定,通过转换VARCHAR(优先级),必须发生涉及VARCHAR
和NVARCHAR
操作数的操作的操作等级27)到NVARCHAR(优先等级25)。因此您的查询非常喜欢
我使用activerecord_sqlserver_adapter来处理Rails activerecord对象的性能问题。这是生成的sql看起来很像并且运行速度非常慢;
SELECT COUNT(*)
FROM [constituents]
WHERE CAST([constituents].[constituent_id] as NVARCHAR(...))
IN (N''10016125'', N''483663'', N''530657'', N''535217'');
这是不可更改的,这意味着将忽略constituent_id
上的索引,而是执行表扫描。
但真正的问题是,为什么你会像int
一样使用字符串来行走和嘎嘎叫? construct_id列不应该是int
,还有传入的参数吗?
答案 1 :(得分:1)
construct_id是字符串还是数字?如果是字符串,是否无法指示您的适配器是varchar还是nvarchar?可能会杀死你的是隐式转换。
您是否考虑过先将值插入表中然后再执行连接?这可以通过传入逗号分隔的字符串然后使用UDF或XML将列表“拆分”为具有匹配数据类型的表来轻松完成。可能会看到SQL query to match keywords?
答案 2 :(得分:1)
'N'表示Unicode字符串。我猜测SQL Server中的类型不是Unicode(即VARCHAR而不是NVARCHAR),因此此代码生成隐式转换。查看执行计划,看看是否可以在运算符中看到convert_implicit。如果是这种情况,您需要弄清楚代码生成器假设变量是Unicode的原因。可能有某种方法可以将变量声明为不会转换为Unicode的不同类型。
答案 3 :(得分:0)
select count进行全表扫描,in子句也很慢,由于select count,查询将进行全表扫描。
将查询分解为小的一行查询。存储计数或使用分区来获得更好的性能。
索引,会有所帮助。