解析大量字符串的最佳方法是什么?

dat*_*god 7 sql-server

我有一个包含超过 400,000,000 条记录的表,我正在寻找有关如何快速解析它的建议。

TheNameTable
(
  NameID  int primary key,
  TheName varchar(500)
)
Run Code Online (Sandbox Code Playgroud)

名称存储如下:“名字,姓氏”(不是我的表,只是我必须使用的)

我需要提取一个唯一的姓氏列表。我最初的想法是以一系列批次(比如一次 50,000 条记录)处理该表,使用 NameID 来控制批次范围。然后我将使用 SQL 的内置字符串函数在“,”处断开字符串并保留字符串的右半部分。

right(TheName,charindex('.',reverse(TheName))-1)
Run Code Online (Sandbox Code Playgroud)

我有一种感觉,这仍然需要很长时间。

有没有人有其他想法?

简单地导出数据并在数据库外处理文件是否值得?

我采用的解决方案:

按照建议,我创建了两个计算列。一个是名字,一个是姓。他们没有坚持,因为我的空间有限。

alter table TheNameTable 
add LastName as substring(TheName, charindex(',',TheName)+1,1000)

alter table TheNameTable 
add FirstName as left(TheName,charindex(',',TheName)-1)
Run Code Online (Sandbox Code Playgroud)

我要求管理员临时增加 RAM,他们将 VM 提高到 32GB。

我创建了一个新表,其中包含 FirstName 和 LastName 的列。我在列上放置了一个唯一的复合索引,但指定了 IGNORE_DUP_KEY = ON。

我刚刚插入了前 1,000,000 条记录。它过滤掉了 125,000 个重复项。整个语句运行耗时 9 秒。

这就是我要找的速度!

Dar*_*ait 6

4 亿个名字很多。我在里面吗?;-)

我的直觉是,使用 substring 不会比通过 CLR 编码东西慢得多。我是一个 SQL 人,我在过去(2000 年或 2005 年)做过大量简单的解析,并且我参与了一个非常复杂的解析方案(地址,全球) c 并通过 xproc 调用,直到我们发现原型“本机”代码并不比用 tsql 函数编写的相同代码快。

如果您想使用 tsql 以外的语言,我建议您使用 c# 或 vb.net 编写 CLR。对于简单的事情,在 CLR 中编码并不难。不到一个早上,我就从新手变成了拥有几个工作目录和文件实用程序。网上有很多简单的 clr 程序的例子。并且您无需学习任何东西(或安装 Visual Studio)即可在 tsql 中编写它

无论如何,您都必须至少浏览一次桌子。如果你导出,然后解析然后放回什么不是少量的数据,那是很多时间。你能保证你的来源不会同时改变吗?

这是每个人似乎总是偷偷摸摸的事情:解析后的数据会发生什么?它在哪里结束?您是否打算更新该行,也许您的示例中没有显示姓氏和名字列?

如果这样做,并且这些列当前为空或其中的字符串长度为零,您可能会发现更新语句的性能非常糟糕,因为 sql 可能必须拆分页面来存储姓氏。

换句话说,您的性能问题不是解析,而是存储解析的数据。通常,这比将数据插入另一个表更糟糕。此外,所有这些页面拆分都会使您的表碎片化并导致查询性能下降,这可能会激怒您的 dba,因为他/她将不得不在(大)表上运行碎片整理程序。

这是最后一个想法:您真的需要存储解析后的数据吗?您可以使用一个计算列来即时计算姓氏吗?如果您需要,这些是可索引的,具有某些条件。另一种方法是公开表的列以及“解析的姓氏列”的视图。