如何对长字符串进行数据库规范化?
How to do database normalization with long string?
我需要一些关于如何规范化当前数据库的建议 table。
目前架构如下:
+----------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| date | date | YES | MUL | NULL | |
| hostname | varchar(255) | YES | | NULL | |
| username | varchar(255) | YES | MUL | NULL | |
| path | varchar(1024) | YES | MUL | NULL | |
| count | int(11) | YES | | NULL | |
+----------+---------------+------+-----+---------+-------+
path
是一个很长的字符串,它经常以相同的值重复多次。我尝试将它移到另一个 table 并将其视为当前 table 的外键。这将节省大量磁盘 space,因为目前我每周有 30M 条记录。
问题是当我将数据插入另一个名为 Path
的 table 时,我不知何故需要知道该路径是否存在。如果是,则获取现有条目并将其作为 FK 分配给当前 table 的新条目,否则在 Path
table 中创建一个新路径条目。我考虑过使 Path
table 中的 path
字段唯一,但 mysql 不允许这样做并给出 Specified key was too long; max key length is 1000 bytes
错误。
我的问题是:最好的方法是什么:
- 检查路径值是否存在于另一个table中
- 如果是,获取其 ID 作为 FK 并在当前 table
中创建一个条目
- 如果没有,创建一个新的路径条目,获取PK作为FK并在当前table
中创建一个条目
后续问题:
现在我正在做一个长字符串连接来组成一个 INSERT INTO
sql 语句来进行数据插入。如果我拆分 table,听起来我需要在插入发生之前进行查找。我认为这会大大减慢该过程。有没有办法避免这种情况?
首先,当您用代理 ID 号替换字符串时,您是在进行数据压缩,而不是规范化。 None 的正常形式需要用数字替换字符串。
I thought about making the path field in Path table unique, but mysql doesn't allow that and gives Specified key was too long; max key length is 1000 bytes
error.
嗯,似乎 Path.path 需要 是独一无二的。你有一些选择。
- 使路径为 1000 字节而不是 1024。
- 切换到对较长值实施唯一约束的 dbms。 PostgreSQL 可以。
- 在应用程序级别检查唯一性,而不是在数据库级别强制执行唯一性。当心竞争条件。编写代码以支持重复路径的报告。 (如 "print a report of duplicate paths"。)最终,您 将 找到重复的路径。
最常见的方法是调用存储过程来插入行。 SP 不首先检查——它只是插入行并捕获由重复键引发的错误。无论如何你都必须捕获错误——除了重复的键之外,很多事情都可能出错。
如果插入成功,SP returns新的ID号。如果它因重复键错误而失败,它会选择现有路径的 ID 号,而不是 returns。如果因其他错误而失败,该怎么办取决于应用程序。
如果先检查再插入,则每次插入都需要往返数据库两次。当您先插入并捕获错误时,您只需要一个新行的圆头。这样可以减轻一点负担。或者很多,取决于你在做什么。
我需要一些关于如何规范化当前数据库的建议 table。
目前架构如下:
+----------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+---------------+------+-----+---------+-------+
| date | date | YES | MUL | NULL | |
| hostname | varchar(255) | YES | | NULL | |
| username | varchar(255) | YES | MUL | NULL | |
| path | varchar(1024) | YES | MUL | NULL | |
| count | int(11) | YES | | NULL | |
+----------+---------------+------+-----+---------+-------+
path
是一个很长的字符串,它经常以相同的值重复多次。我尝试将它移到另一个 table 并将其视为当前 table 的外键。这将节省大量磁盘 space,因为目前我每周有 30M 条记录。
问题是当我将数据插入另一个名为 Path
的 table 时,我不知何故需要知道该路径是否存在。如果是,则获取现有条目并将其作为 FK 分配给当前 table 的新条目,否则在 Path
table 中创建一个新路径条目。我考虑过使 Path
table 中的 path
字段唯一,但 mysql 不允许这样做并给出 Specified key was too long; max key length is 1000 bytes
错误。
我的问题是:最好的方法是什么:
- 检查路径值是否存在于另一个table中
- 如果是,获取其 ID 作为 FK 并在当前 table 中创建一个条目
- 如果没有,创建一个新的路径条目,获取PK作为FK并在当前table 中创建一个条目
后续问题:
现在我正在做一个长字符串连接来组成一个 INSERT INTO
sql 语句来进行数据插入。如果我拆分 table,听起来我需要在插入发生之前进行查找。我认为这会大大减慢该过程。有没有办法避免这种情况?
首先,当您用代理 ID 号替换字符串时,您是在进行数据压缩,而不是规范化。 None 的正常形式需要用数字替换字符串。
I thought about making the path field in Path table unique, but mysql doesn't allow that and gives
Specified key was too long; max key length is 1000 bytes
error.
嗯,似乎 Path.path 需要 是独一无二的。你有一些选择。
- 使路径为 1000 字节而不是 1024。
- 切换到对较长值实施唯一约束的 dbms。 PostgreSQL 可以。
- 在应用程序级别检查唯一性,而不是在数据库级别强制执行唯一性。当心竞争条件。编写代码以支持重复路径的报告。 (如 "print a report of duplicate paths"。)最终,您 将 找到重复的路径。
最常见的方法是调用存储过程来插入行。 SP 不首先检查——它只是插入行并捕获由重复键引发的错误。无论如何你都必须捕获错误——除了重复的键之外,很多事情都可能出错。
如果插入成功,SP returns新的ID号。如果它因重复键错误而失败,它会选择现有路径的 ID 号,而不是 returns。如果因其他错误而失败,该怎么办取决于应用程序。
如果先检查再插入,则每次插入都需要往返数据库两次。当您先插入并捕获错误时,您只需要一个新行的圆头。这样可以减轻一点负担。或者很多,取决于你在做什么。