4

我有以下查询在 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>

如果我执行相同的查询但使用 cfqueryparam,它会在 500 毫秒 - 2000 毫秒内运行。

<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>

该表大约有 60,000 行。“散列”列是 varchar(50) 并且具有唯一的非聚集索引,但不是主键。数据库服务器是 MSSQL 2008。Web 服务器运行的是最新版本的 CF9。

知道为什么 cfqueryparam 会导致性能爆炸吗?无论我刷新页面多少次,它每次都以这种方式运行。如果我将列表配对到只有 2 或 3 个哈希,它在 150-200 毫秒时仍然表现不佳。当我消除 cfqueryparam 时,性能符合预期。在这种情况下,存在 SQL 注入的可能性,因此使用 cfqueryparam 肯定会更好,但从索引列中查找 2 条记录不应该花费 100 毫秒。

编辑:

  1. 我们使用hash()不是 UUIDS 或 GUIDS 生成的哈希值。哈希由 a 生成,hash(SerializeJSON({ struct }))其中包含要在图像上执行的一组操作的计划。这样做的目的是让我们在插入之前和查询之前知道该结构的确切唯一 ID。这些散列充当了已经存储在数据库中的结构的“索引”。除了散列,相同的结构将散列到相同的结果,这对于 UUIDS 和 GUIDS 是不正确的。

  2. 该查询正在 5 个不同的 CF9 服务器上执行,它们都表现出相同的行为。对我来说,这排除了 CF9 正在缓存某些东西的想法。所有服务器都连接到完全相同的数据库,因此如果发生缓存,它必须是数据库级别。

4

3 回答 3

8

您的问题可能与 VARCHAR 与 NVARCHAR 有关。这 2 个链接可能有助于 在 SQL Server 中从 ColdFusion和 nvarchar 与 varchar查询 MS SQL Server G/UUID ,请注意

可能发生的情况是 ColdFusion 管理员中有一个设置是否cfqueryparam将 varchars 作为 unicode 发送。如果该设置与列设置不匹配(在您的情况下,如果启用了该设置),则 MS SQL 将不会使用该索引。

于 2012-05-11T16:28:05.200 回答
0

正如马克指出的那样,缓存中可能有一个错误的执行计划。cfqueryparam 的优点之一是,当您传入不同的值时,它可以重用它为该语句提供的缓存计划。这就是为什么当您尝试使用较小的列表时您看不到任何改进的原因。当您不使用 cfqueryparam 时,SQL Server 每次都必须制定执行计划。这通常是一件坏事,除非它在缓存中有一个次优计划。尝试按照此处http://www.devx.com/tips/Tip/14401的说明清除缓存,希望这意味着下次您使用 cfqueryparam 运行语句时,它会缓存更好的计划。

有道理?

于 2012-05-11T05:04:23.840 回答
0

我认为 cfqueryparam 不会引起问题。正如您提到的执行中的大幅提升,在尝试使用 cfqueryparam 时,索引可能不会用于您的查询。我在我的开发计算机上创建了相同的场景,但是在使用和不使用 cfqueryparam 的情况下我得到了相同的执行时间。使用列表可能会有一些开销,因为在第一个查询中您直接将其作为测试传递,而在第二个冷融合中需要从提供的列表中的查询参数创建,但这也不应该那么多。我会建议启动“SQL Server Profiler”并监控在服务器上执行的查询,这会让你更好地花费另外 500 毫秒。

于 2012-05-11T05:26:27.563 回答