在一行的一个字段中存储多个值而不是作为单独的行存储多个值的可能好处

Hum*_*All 12 database-design sql-server denormalization

在我们上一次每周例会上,一个没有数据库管理背景经验的人提出了这个问题:

“会不会有一种情况证明将数据存储在行(字符串)而不是多行中是合理的?”

让我们假设有一个表,称为countryStates我们想要存储一个国家的州的位置;我将在这个例子中使用美国,为了懒惰,不会列出所有的州。

在那里我们会有两列;一个叫Country,另一个叫States。正如这里所讨论的,以及@srutzky 的回答所提出的,这PK将是ISO 3166-1 alpha-3定义的代码。

我们的表看起来像这样:

+---------+-----------------------+-------------------------------------------------------+
| Country | States                | StateName                                             |
+---------+-----------------------+-------------------------------------------------------+
| USA     | AL, CA, FL,OH, NY, WY | Alabama, California, Florida, Ohio, New York, Wyoming |
+---------+-----------------------+-------------------------------------------------------+
Run Code Online (Sandbox Code Playgroud)

当向一位开发人员朋友提出同样的问题时,他说从数据流量大小的角度来看,这可能有用,但如果我们需要操纵这些数据,则不是。在这种情况下,应用程序代码必须有智能,可以在列表中转换此字符串(假设有权访问此表的软件需要创建一个组合框)。

我们得出的结论是这个模型不是很有用,但我怀疑可能有办法让它有用。

我想问的是,你们中是否有人已经以真正有效的方式看到、听到或做过这样的事情。

Sol*_*zky 13

首先,当前的问题标题提到“将数据存储为字符串而不是列”有点令人困惑。当谈到将数据存储为字符串而不是其他内容时,这通常是指将所有内容序列化为字符串格式而不是正确/强数据类型(例如INTDATETIME)。但是,如果询问将数据存储为单个字段中的多个值而不是单独的行,那就有点不同了。公平地说,虽然连接值最容易用字符串完成,但也可以用INTBINARY类型完成,通过位掩码或类似地保留某些位置以具有不同的含义。由于第二种解释是实际被问到的内容,因此根据问题的文本,让我们解决这个问题。

一句话:不。如果您要存储实际数据点,那么它只会带来痛苦(在代码和性能方面),因为它是不必要的复杂化。如果它是一个只会作为一个单元存储、作为一个单元更新并且永远不会在数据库中分解的值,那么这可能没问题,因为它大致类似于存储图像或 PDF。否则,任何解析数据的尝试都将因使用任何索引(例如,使用LIKE '%something%'、 或CHARINDEX、 或PATINDEX、 或SUBSTRING等)而失效。

如果您需要在单行的单个字段中存储单独的值,那么有更合适的方法来做到这一点:XML 或 JSON。这些是可解析的格式(XML / JSON),而且 XML 甚至可以编入索引。但理想情况下,这些数据将存储在正确类型的字段中,以便它真正有用。

并且请不要忘记,RDBMS 的目的是存储数据,以便在符合ACID的约束下尽可能高效地检索操作数据。由于需要首先解析值,并且不可索引,因此检索连接值已经够糟糕的了。但是操作通常意味着替换整个 blob 只是为了更新它的一部分(假设不存在与函数一起使用的模式)。XML 数据类型至少允许XML DML进行简单的更新,尽管这些仍然不如正确建模数据的简单更新快。REPLACE

此外,鉴于上述问题中所示的场景,通过将所有 StateCode 连接在一起,您将无法外键(在任一方向)这些值。

如果业务需求随时间发生变化并且您需要跟踪这些项目的其他属性,该怎么办?就“州”而言,首都、人口、排序顺序或其他任何东西呢?正确存储为行,您可以为其他属性添加更多列。当然,您可以拥有多个级别的可解析数据,例如|StateCode,Capital,Population |StateCode,Capital,Populate|...但希望任何人都能看到问题呈指数级增长失控。当然,这个特殊问题很容易用 XML 和 JSON 格式处理,这就是上面提到的它们的价值。但你还是需要一个非常使用或者作为那些既不造型的最初手段将永远被视为有效作为单独的行使用离散场很好的理由。


Ken*_*her 9

我实际上已经将类似的东西用于非常有限的目的。我们为输出文件创建了一个标题表。它们是专门构建的,主要只是列标题,但不完全是。所以数据看起来像

OutputType   OutputHeader
PersonalData Name|Address|City|State|Zip
JobInfo      Name|JobName|JobTitle
Run Code Online (Sandbox Code Playgroud)

本质上,它看起来像是一个分隔列表。一方面是这样。但就我们的目的而言,它是一个长字符串。

这就是这里的诀窍。如果您从不打算解析列表,那么保存列表是值得的。但是,如果您将或什至可能需要解析列表,那么值得花额外的空间和时间将其拆分并将其保存在单独的行中。