从varchar(max)列获取SQL Server表中所有数据的最有效方法

时间:2009-10-01 19:18:58

标签: sql-server

这个问题适用于SQL Server 2005。

我有一个有2列的表。

Table_A
    Id Guid (PrimaryKey)
    TextContent varchar(max)

该表包含大约7000条记录,textcontent范围为0 - 150K +。

当我做一个select语句时       SELECT Id,TextContent FROM Table_A ,花了很长时间大约10分钟。

是否有更好的方法可以将所有数据排除在表格之外?

在主要执行期间,我只加载某些记录。示例: SELECT Id,TextContent FROM TableA WHERE ID IN(@ id0,@ id1,@ id2,@ id3 .... @ id20)。这个查询并不慢,但也不是那么快。我想看看我是否可以通过在运行时之前拉动TextContent来优化过程。这个过程可以在一两分钟内运行,但10分钟是不可接受的。

6 个答案:

答案 0 :(得分:2)

GUID是主键,默认情况下也是你的集群密钥,毫无疑问会导致大的碎片 - 但考虑到列的性质,varchar(max)将会定期在页面中LOB存储并且不存储在页面上,除非它符合8060限制。

如果您将GUID设置为主要的GUID,那么碎片不会有所帮助 - 您可以使用DMV sys.dm_db_index_physical_stats检查碎片级别

除非每行的平均数据量很高,否则我认为碎片确实不是问题。正常超过8k。

如果是,......碎片开始受到伤害。最坏的情况是每页1行,7k I / O并不理想,但每个LOB存储平均100k,你可能会看到更多的87k I / O和数据写入的顺序等会导致什么应该是对表(和磁盘)的顺序扫描,变成一个大规模的随机I / O节,因为磁盘在带有行+ LOB指针和LOB页面的页面之间来回长行程。 除此之外,机会te GUID是聚类键,因此它甚至无法扫描数据页而没有相当多的磁头移动。

我还必须同意Erich的意见,即您尝试通过网络传输的数据量将导致链路不足的延迟,您应该通过分页或合适的查询在服务器级别正确过滤数据。

我知道您希望预先缓存数据,这有时可以正常工作 - 但它正在如此庞大的实体上执行,它往往表明其他错误并且您正在修复错误的问题。

一个。

答案 1 :(得分:1)

我对此表示怀疑。如果你想“从表中获取所有数据”,那么你必须读取表中存储的每个字节,这可能需要大量的物理磁盘I / O.

也许你想要的只是从表中检索一些数据?

答案 2 :(得分:1)

这是从表中获取数据的正确方法,除非您只需要1行。如果您只需要1行,只需使用正确的查询。

您使用的是哪种网络连接?让我们这样说,你有7000条记录。每个包含平均100k的数据(为了方便,如果它比这更多或更少,那很好,我的观点仍然存在)。总查询将返回700 MB的数据!即使通过极快的连接,也可轻松下载10分钟。

即使在完美的100兆位连接下,转移也需要将近一分钟!此外,您必须从物理磁盘中获取该数据,这将需要一段时间。

我建议进行某种分页,以便将数据放入较小的位置。

答案 3 :(得分:1)

您的Id列是GUID。你使用的是默认值吗?是NewID()?我认为它集中在PK上。

如果您使用NewSequentialID()作为默认设置,您将获得更少的页面拆分,因此您的数据将分布在更少的物理页面上。

有了大量的数据,这是我唯一能看到的有助于提高性能的数据。

答案 4 :(得分:0)

正如许多人提到的那样,你正在获取大量数据。首先确保你是否真的需要所有行。

如果您这样做,请不要一次性获取所有内容 - 请改用LIMIT。这实际上会降低速度,但是如果有任何失败,你只需要再次加载一小段,而不必再等10分钟。

SELECT Id, TextContent FROM Table_A LIMIT 0, 30

此查询将获取表格的前30个条目。与

SELECT Id, TextContent FROM Table_A LIMIT 30, 30

你会得到下一件作品。

也许您可以向我们提供更多信息,例如您想要对数据做什么以及您使用哪种编程语言?

答案 5 :(得分:-2)

1)不要使用SELECT *,始终列出您的列,无论是1,2还是100 2)尝试查看索引

150k字符?在那个领域?那是你指的是什么?