【问题标题】:Adding datalength condition makes query slow添加数据长度条件使查询变慢
【发布时间】:2012-12-06 11:14:25
【问题描述】:

我有一个 mytable 表,其中包含一些列,包括 datekey 列(这是一个 date 并有一个索引)、一个列 contents 这是一个 varbinary(max) 和一个列 stringhash 这是varchar(100)stringhashdatekey 一起构成了表的主键。一切都在我的本地机器上运行。

跑步

SELECT TOP 1 * FROM mytable where datekey='2012-12-05'

返回 0 行,耗时 0 秒。 但是如果我添加一个datalength 条件:

SELECT TOP 1 * FROM mytable where datekey='2012-12-05' and datalength(contents)=0

它运行了很长时间,在我放弃等待之前没有返回任何东西。

我的问题: 为什么?我如何找出这需要这么长时间的原因?


这是我目前检查的内容:

当我点击“显示估计的执行计划”时,它也需要很长时间,并且在我放弃等待之前没有返回任何内容。

如果我这样做

SELECT TOP 1000 datalength(contents) FROM mytable order by datalength(contents) desc

耗时 7 秒,返回列表 4228081、4218689 等。

exec sp_spaceused 'mytable'

返回

rows        reserved     data         index_size  unused
564019      50755752 KB  50705672 KB  42928 KB    7152 KB

所以这个表相当大,有 50 GB。 跑步

SELECT TOP 1000 * FROM mytable

需要 26 秒。

sqlservr.exe 进程大约 6 GB,这是我为数据库设置的限制。

【问题讨论】:

    标签: sql-server performance sql-server-2012 datalength


    【解决方案1】:

    这需要很长时间,因为您的查询需要为每一行评估 DATALENGTH,然后对结果进行排序,然后才能返回第一条记录。 如果字段的 DATALENGTH(或者它是否包含任何值)是您可能会重复查询的内容,我建议您使用一个额外的索引字段(可能是一个持久计算字段)来保存结果,并在其上进行搜索。

    【讨论】:

    • 为什么 SQL Server 不更智能,只为具有匹配 datekey 的行而不是每一行评估 datalength?嵌套查询是否会首先评估 datekey 匹配?
    【解决方案2】:

    这个旧的msdn blog post 似乎同意@MartW 的回答,即对每一行评估datalength。但最好了解“已评估”的真正含义以及性能下降的真正根源是什么。

    如问题中所述,contents 列中每个值的大小可能很大。这意味着每个大于 ~8Kb 的值都存储在特殊的 LOB 存储中。因此,考虑到其他列的大小,很明显,该表占用的大部分空间都被此 LOB 存储占用,即大约 50Gb。

    即使已经评估了每行的contents 列的长度,这在上面链接的帖子中得到了证明,它仍然存储在 LOB 中。所以引擎仍然需要读取 LOB 存储的某些部分来执行查询。

    如果查询执行时 LOB 存储不在 RAM 中,那么我们需要从磁盘读取它,这当然比从 RAM 慢得多。 LOB 部分的读取也可能是随机的,而不是线性的,这甚至更慢,因为它往往会增加需要从磁盘读取的内存块的总数。

    【讨论】:

      【解决方案3】:

      目前它可能不会使用主键,因为在 datekey 列之前包含 stringhash 列。尝试添加仅包含 datekey 列的附加索引。一旦创建了该键,如果它仍然很慢,您还可以尝试查询提示,例如:

      SELECT TOP 1 * FROM mytable where datekey='2012-12-05' and datalength(contents)=0 WITH INDEX = IX_datekey
      

      您还可以创建一个单独的长度列,该列在您的应用程序或插入/更新触发器中更新。

      【讨论】:

        猜你喜欢
        • 2020-06-17
        • 1970-01-01
        • 2022-10-24
        • 2014-02-17
        • 2018-10-24
        • 1970-01-01
        • 2020-12-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多