我一直能够通过Coldfusion 10查询SQL Server 2008 R2来重现严重的参数化性能问题,并且有兴趣知道其他人得到了什么.代码如下.
测试做了什么? 它创建一个包含100行的表.除一个数据列外,数据列均为空白.然后它运行Coldfusion查询10次,一半使用cfqueryparam,一半使用简单的字符串.它返回一个列表,其中包含每个响应时间.当我运行它时,除了初始调用之外,参数化查询的运行速度要慢得多(大约10-100次).
SQL Server中发生了什么? 我可以看到SQL服务器没有区别.在这两种情况下,计划缓存指示几乎相同的计划(一个显然是参数化的),并且剖析器显示两者的快速响应.然而,Coldfusion与参数化查询斗争.
什么解决了这个问题? 奇怪的是,如果我将varchar更改为nvarchar,问题就会消失.或者如果我将非空白移动到开头,则两个响应都很慢(如图所示).如果我将所有记录留空或非空白,那么问题就不存在了.它必须是混合物.我不能在CF9中重现这个问题,但还没有尝试过CF11.
<cfset datasource="yourdatasource" />
<cfquery name="createdata" datasource="#datasource#">
--EMPTY PREVIOUS TESTS
IF OBJECT_ID('aaatest', 'U') IS NOT NULL
BEGIN
TRUNCATE TABLE aaatest;
DROP TABLE aaatest;
END
--CREATE TABLE TO CONTAIN DATA
CREATE TABLE [dbo].[aaatest](
[id] [int] NOT NULL,
[somedata] [varchar](max) NULL,
[somekey] [int] NOT NULL
) ON [PRIMARY];
--INSERT 100 ROWS WITH 99 BLANK AND 1 NON-BLANK
WITH datatable AS (
SELECT 1 id
UNION all
SELECT id + 1
FROM …Run Code Online (Sandbox Code Playgroud) 我遇到了一个与安全相关的奇怪问题,最近我尝试在nvarchar(130)的SQL Server数据库字段中插入散列密码时遇到了常规但间歇性的错误:
<cfqueryparam value="#hashpass#" cfsqltype="cf_sql_char" maxLength="130">
Run Code Online (Sandbox Code Playgroud)
因此设置了hashpass变量:
<cfset hashpass = Hash(arguments.password & getsalt.user_salt, "SHA-512")>
Run Code Online (Sandbox Code Playgroud)
想知道SHA-512哈希值如何超过128个字符,当文档说它应该总是128个?这是ColdFusion 10错误:
[Macromedia] [SQLServer JDBC驱动程序] [SQLServer]字符串或二进制数据将被截断.
我有以下查询在16毫秒 - 30毫秒运行.
<cfquery name="local.test1" datasource="imagecdn">
SELECT hash FROM jobs WHERE hash in(
'EBDA95630915EB80709C69089315399B',
'3617B8E6CF0C62ECBD3C48DDF8585466',
'D519A38F09FDA868A2FEF1C55C9FEE76',
'135F94C3774F7719CFF8FF3A275D2D05',
'D58FAE69C559273D8427673A08193789',
'2BD7276F209768F2FCA6635659D7922A',
'B1E3CFBFCCFF6F5B48A849A050E6D424',
'2288F5B8A797F5302E8CA24323617236',
'8951883E36B5D38A4643DFAA0396BF13',
'839210BD564E30BE1355D1A6D4EF7081',
'ED4A2CB0C28B608C29576819CF7BE19B',
'CB26925A4874945B810707D5FF0B91F2',
'33B2FC229F0CC797A02AD163CDBA0875',
'624986E7547DBAC0F47B3005CFDE0A16',
'6F692C289BD805CEE41EF59F83F16F4D',
'8551F0033C617BD9EADAAD6CEC4B3E9E',
'94C3C0A74C2DE085FF9F1BBF928821A4',
'28DC1A9D2A69C2EDF5E6C0E6368A0B3C'
)
</cfquery>
Run Code Online (Sandbox Code Playgroud)
如果我执行相同的查询但使用cfqueryparam它运行500ms - 2000ms.
<cfset local.hashes = "[list of the same ids as above]">
<cfquery name="local.test2" datasource="imagecdn">
SELECT hash FROM jobs WHERE hash in(
<cfqueryparam cfsqltype="cf_sql_varchar" value="#local.hashes#" list="yes">
)
</cfquery>
Run Code Online (Sandbox Code Playgroud)
该表大约有60,000行."hash"列是varchar(50)并且具有唯一的非聚集索引,但不是主键.数据库服务器是MSSQL 2008.Web服务器正在运行最新版本的CF9.
知道为什么cfqueryparam会导致性能轰炸吗?无论我刷新页面多少次,它每次都会以这种方式运行.如果我将列表配对只有2或3个哈希值,它仍然表现不佳,如150-200ms.当我取消cfqueryparam时,性能如预期.在这种情况下,有可能进行SQL注入,因此使用cfqueryparam肯定会更好,但是从索引列中找到2条记录不应该花费100毫秒.
编辑:
我们使用的hash()是非UUIDS或GUIDS 生成的哈希.散列由a生成,hash(SerializeJSON({ struct }))其中包含要在映像上执行的一组操作的计划.这样做的目的是它允许我们在插入之前和查询之前知道该结构的确切唯一ID.这些哈希充当已经存储在DB中的结构的"索引".除了哈希之外,相同的结构将散列到相同的结果,这对UUIDS和GUIDS来说是不正确的.
该查询正在5个不同的CF9服务器上执行,并且所有这些服务器都表现出相同的行为.对我来说,这排除了CF9缓存某些东西的想法.所有服务器都连接到完全相同的DB,因此如果发生缓存,则必须是数据库级别.