【问题标题】:Slow "Select" Query with varchar(max)使用 varchar(max) 进行慢速“选择”查询
【发布时间】:2012-05-29 06:47:30
【问题描述】:

我有一张 500 行的小桌子。 该表有 10 列,包括 1 个 varchar(max) 列。

当我执行这个查询时:

SELECT TOP 36 *
FROM MyTable
WHERE (Column1 = Value1)

它在 3 分钟内检索了大约 36 行。 varchar(max) 列每行包含 3000 个字符。

如果我尝试只检索少一行:

SELECT TOP 35 *
FROM MyTable
WHERE (Column1 = Value1)

然后查询在 0 秒内检索 35 行。

在我的客户统计数据中,从服务器收到的字节数:

95 292 表示查询在 0 秒内检索数据

查询在 3 分钟内检索数据超过 200 000 000

你知道它是从哪里来的吗?

编辑 --- 这是我的真实代码:

select top 36 *
from Snapshots
where ExamId = 212

select top 35 *
from Snapshots
where ExamId = 212

编辑 --- 有关客户统计的更多信息

变化很大的两个统计数据是:

从服务器接收的字节数:66 038 Vs 超过 2 000 000

从服务器 30 Vs 11000 收到的 TDS 数据包

【问题讨论】:

  • 如果问题已经存在,请发送查询计划。
  • @Toc 你解决了吗?我正在运行完全相同的问题。只有 10 条记录,1 列带有 nvarchar(max) 和一些数据,但没有什么疯狂的。完成前 1 名需要 3 分钟。

标签: sql-server sql-server-2008-r2


【解决方案1】:

使用Index 代替ExamId 也使用select field1,field2,etc 代替select * ...

【讨论】:

  • 试过了。不会改变任何东西
【解决方案2】:

我不确定,但试试这个:

select * from Snapshots where ExamId = (select top 36 ExamId from Snapshots where ExamId = 212)

【讨论】:

  • 我试过了(并用“in”替换了“=”),但没有任何改变
【解决方案3】:

您的执行时间应该非常短,而 fetch 则要长得多。 从 SELECT TOP 语句中删除 varchar(max) 并仅在您特别需要时检索这些值。

【讨论】:

    【解决方案4】:

    在运行 SELECT 查询之前包含 SET STATISTICS IO ON 并提供输出。此外,您能否发布来自 2 个不同查询的查询计划,因为这将大大有助于解释差异是什么。您可以使用https://www.brentozar.com/pastetheplan/ 上传并提供链接。

    您的TOP 也没有匹配的ORDER BY,因此您无法保证返回的前35 或36 行的顺序。这意味着 35 行可能不会全部包含在 36 行中,您可能返回的数据量大不相同。

    最后,还可以尝试在 SSMS 中通过查询启用 Client Statistics - 这将显示延迟是在服务器端还是在向您返回结果集时的全部延迟。

    【讨论】:

      【解决方案5】:

      如果没有完整的表描述作为 DDL 语句 (CREATE TABLE...) 和索引,则很难回答。

      一个重要的问题是:您在创建表时使用“指令”TEXTIMAGE_ON 吗?这会将 LOB 存储与关系数据分开,以避免行溢出存储...

      【讨论】:

        【解决方案6】:

        Varchar(max) 不能成为索引键的一部分,除了这个其他主要缺点之外,它不能作为连续的内存区域在内部存储,因为它们可能会增长到 2Gb。因此,为了提高性能,您需要避免它。

        【讨论】:

        • 请添加更多详细信息以扩展您的答案,例如工作代码或文档引用。
        【解决方案7】:

        正如其他人所说,您应该扔 schema (datatype+existing index) of Snapshot table。

        snapshot 表中,我相信examid 是非聚集索引,它不是唯一的。 一个examid 有很多记录。快照表必须有任何PK 列。

        Top 子句应始终与Order by 子句一起使用。没有Order by 子句的Top 子句为Non Determinstic。 在什么基础上它将选择Top N。 所以知道快照的模式然后决定正确的索引。

        使用Order by 子句也可以是Non Determinstic 但这是另一个讨论。

        你可以试试这个,

        create  table #temp(PKID int)
        
        insert into #temp(pkid)
        select top 36 pkid
        from dbo.Snapshots
        where ExamId = 212
        

        那么你就可以这样做了,

        select col1,col2,col3,col4
        from dbo.Snapshots S
        where exists(select 1 from #temp t where t.pkid=s.pkid)
        

        现在你的主要问题和问题,

        为什么 0 秒检索 35 行,3 分钟检索 36 行。

        我会很快写到这里。同时我正在等待快照表的完整结构。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-03-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多