为4000万条记录的表添加多列主键

2024-03-12

我正在维护一个数据库,该数据库存储不同网络之间的数据传输信息。本质上,每次数据传输都会被记录下来,并在每个月末运行一个 perl 脚本,将日志文件加载到数据库的表中。我没有设计 Perl 脚本或数据库模式。这是在我开始从事这个项目之前完成的。

I used this http://wiki.postgresql.org/wiki/Retrieve_primary_key_columns用于检索表主键的链接(usage_detail 是表的名称),但它没有给我任何信息。由于表中有如此多的记录,因此跟踪重复项并不容易。我们遇到了加载大量重复项的问题(因为错误脚本会为每次传输进行日志记录,但那是另一个主题),最终不得不删除最新的加载并在修复日志文件后重新加载所有新的加载。正如您可能已经猜到的那样,这是愚蠢且乏味的。

为了解决这个问题,我想向表添加一个主键。由于多种原因,我们不想为主键添加整个新列。查看这些字段后,我找到了一个多列主键。基本上它包括:传输开始时间戳、传输结束时间戳、传输文件的名称(还包括整个路径)。似乎不太可能有两条记录的这些字段相同。

这是我的问题: 1)如果我在表中添加此主键,表中可能已存在的任何重复项会发生什么?

2)我实际上如何将此主键添加到表中(我们使用的是 PostgreSQL 8.1.22)。

3)添加主键后,假设加载脚本运行时它会尝试加载重复项。 PostgreSQL 会抛出什么样的错误?我能在脚本中捕捉到它吗?

4)我知道您没有太多有关加载脚本的信息,但是根据我提供的信息,您是否预见到脚本中可能需要更改的内容?

任何帮助是极大的赞赏。 谢谢。


使用串行列

您的计划是为 4000 万(!)行添加一个不必要的巨大索引。你甚至不确定它是否是独一无二的。我强烈建议反对这种行动路线。添加一个serial http://www.postgresql.org/docs/current/interactive/datatype-numeric.html#DATATYPE-SERIAL列代替并完成它:

ALTER TABLE tbl ADD COLUMN tbl_id serial PRIMARY KEY;

这就是您需要做的全部。其余的事情会自动发生。更多内容请参见手册或这些密切相关的答案:
PostgreSQL主键自增在C++中崩溃 https://stackoverflow.com/questions/7769481/postgresql-primary-key-auto-increment-crashes-in-c/7769763#7769763
自动递增SQL函数 https://stackoverflow.com/questions/9875223/auto-increment-sql-function/9875517#9875517

添加一个serial色谱柱是一次性操作,但价格昂贵。整个表必须被重写,从而在操作期间阻止更新。最好在下班时间没有并发负载的情况下完成。我引用手册在这里 http://www.postgresql.org/docs/current/interactive/sql-altertable.html#AEN64781:

添加具有非空默认值的列或更改列的类型 现有列将需要整个表和索引 重写。 [...] 表和/或索引重建可能需要花费大量时间 一张大桌子的时间量;并暂时需要尽可能多的 磁盘空间的两倍。

由于这有效地重写了整个表,因此您还可以创建一个包含序列 pk 列的新表,插入旧表中的所有行,让序列填充其序列中的默认值,删除旧表并重命名新表。这些密切相关的答案中有更多内容:
在 PostgreSQL 9.2 中更新数据库行而不锁定表 https://stackoverflow.com/questions/15770734/updating-database-rows-without-locking-the-table-in-postgresql-9-2/15771103#15771103
添加新列而不加表锁? https://stackoverflow.com/questions/10412078/add-new-column-without-table-lock/10412790#10412790

确保所有 INSERT 语句都有一个目标列表,然后附加列就不会混淆它们:

INSERT INTO tbl (col1, col2, ...) VALUES ...

Not:


INSERT INTO tbl VALUES ...  

A serial是用一个实现的integer列(4 字节)。
主键约束是通过唯一索引和NOT NULL对所涉及列的约束。
索引内容的存储方式与表非常相似。需要单独额外的物理存储。有关物理存储的更多信息,请参阅此相关答案:
PostgreSQL 中的计算和节省空间 https://stackoverflow.com/questions/2966524/calculating-and-saving-space-in-postgresql/7431468#7431468

您的索引将包含 2 个时间戳(2 x 8 字节)以及一个冗长的文件名(包括)。路径(~ 50 字节?) 这将使索引增大约 2.5 GB(40M x 60 .. 一些字节)并且所有操作都会变慢。

处理重复项

如何处理“导入重复项”取决于您导入数据的方式以及如何准确定义“重复项”。

如果我们谈论的是COPY http://www.postgresql.org/docs/current/interactive/sql-copy.html语句,一种方法是使用临时临时表并使用简单的方法折叠重复项SELECT DISTINCT or DISTINCT ON in the INSERT命令:

CREATE TEMP TABLE tbl_tmp AS
SELECT * FROM tbl LIMIT 0;     -- copy structure without data and constraints

COPY tbl_tmp FROM '/path/to/file.csv';

INSERT INTO tbl (col1, col2, col3)
SELECT DISTINCT ON (col1, col2)
       col1, col2, col3 FROM tbl_tmp;

或者,也禁止与已存在的行重复:

INSERT INTO tbl (col1, col2, col3)
SELECT i.*
FROM  (
   SELECT DISTINCT ON (col1, col2)
          col1, col2, col3
   FROM   tbl_tmp
   ) i
LEFT   JOIN tbl t USING (col1, col2)
WHERE  t.col1 IS NULL;

温度。表会在会话结束时自动删除。

但正确的解决方法是首先处理产生重复的错误的根源。

原问题

1)如果所有列上都有一个重复项,则根本无法添加 pk。

2)我只会接触 PostgreSQL 数据库8.1版本用一根五英尺长的杆子。它极其古老、过时且效率低下,不再受支持,并且可能存在许多未修复的安全漏洞。Postgres 官方版本控制网站。 http://www.postgresql.org/support/versioning/
@David https://stackoverflow.com/a/17089359/939860已经提供了 SQL 语句。

3 & 4) 重复密钥违规。 PostgreSQL 抛出错误也意味着整个事务被回滚。在 Perl 脚本中捕捉到这一点无法使事务的其余部分完成。例如,您必须使用 plpgsql 创建一个服务器端脚本,您可以在其中捕获异常。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为4000万条记录的表添加多列主键 的相关文章

随机推荐

  • Websocket Java 服务器。不发送消息也不接收消息

    我正在尝试制作一个 Java WebSocket 服务器 没有什么真正复杂的 只是一个丑陋的小服务器 用于使用标准定义的 api 从浏览器尝试 websocket 我一直在阅读协议的规范 它非常简单 我已经握手了 显然它正在起作用 我用Ja
  • 附加分配给特定分区的 KafaConsumer

    如何将 python 消费者脚本附加到特定的 kafka 分区 在运行消费者脚本的两个实例 如下所示 时 每个实例都会随机选择一个分区 然后按预期消费 打印该特定分区的所有消息 但由于我需要将这些消息输出到磁盘上名为本地文件的分区 因此将脚
  • 用于存储数百万张图像的文件夹结构?

    我正在构建一个网站 该网站正在查看轻松上传的数百万张照片 每个上传的图像都有 3 个缩略图 我需要找到存储所有这些图像的最佳方法 我搜索并找到了存储为哈希的图像示例 例如 如果我上传 coolparty jpg 我的脚本会将其转换为 Md5
  • 数据仓库模型:集线器有什么用?

    我刚刚读到数据仓库建模 https en wikipedia org wiki Data vault modeling据我了解 集线器仅包含密钥 和记录源 所以我想知道为什么我应该创建这些中心表 只是为了存储记录源 仅拥有卫星和链接还不够吗
  • NSValueTranformer 用于加密数据

    我想在 NSValueTransformer 的帮助下加密一些核心数据列 我的想法是 我使用数据类型可转换并为我的数据类型定义一些转换器 在转换方法中 我想加密 解密该值 我定义了一个实际上什么都不做的变压器 加密的东西目前还没有实现 im
  • ReportViewer 到 div/image/object 内的 PDF

    这几天一直在寻找 但没能找到我要找的东西 希望我没有错过 我有一个 ASP NET 4 0 站点 我正在将其放在一起以检索工资信息 目前我正在使用reportviewer 但由于跨浏览器支持 它不能100 工作 我已经将其设置为自动将 RV
  • Symfony2 形成没有实体的验证器组

    我正在使用 Symfony2 表单组件来构建和验证表单 现在我需要根据单个字段值设置验证器组 不幸的是 似乎每个示例都基于实体 由于多种原因 我没有使用实体 例子 如果任务为空 则应删除所有约束验证器 但如果不是 则应使用默认的验证器集 或
  • 使用 spring RestTemplate 来自 Android 的 PUT 请求

    我必须通过 Restful 服务 Net 将客户对象从 Android 客户端放入数据库 服务合同 WebInvoke Method PUT UriTemplate customers customerId RequestFormat We
  • 我可以将同一个 Firebase 用于两个不同的应用吗?

    我想为两个应用程序使用相同的 Firebase 在这两个应用程序中 用户应该能够通过 Google Facebook 或电子邮件登录 但在我的 Firebase 仪表板的 登录和身份验证 部分中 我只能添加一个 Facebook 应用程序
  • 用不同的方式从列表中删除重复项

    我有一个名为employee的类 它是pojo 并且我创建了该pojo类型的employee类型的列表 现在我想从列表中删除重复项 请告知实现这一目标的各种方法是什么 class Emp implements Comparable Stri
  • 无法在经典 asp 中写入文件

    好吧 自从我使用经典的 asp 以来已经有一段时间了 所以我有点生疏了 这是我的问题 我正在尝试使用 FSO 将文件写入文件系统 下面的代码非常简单 但是 该文件没有出现 也没有出现错误 我知道它正在运行代码 因为我可以在此片段之前和之后添
  • 无法打开源文件:“WIN32”:没有这样的文件或目录

    在 VS2008 中构建 C 项目时出现此错误 很困惑这是什么意思 为什么它认为WIN32是一个文件 Go to Project gt 特性 gt C C gt 命令行 你很可能有一个 I 在你之前 D WIN32 由于某种原因 空的 in
  • 在 Typescript 上获取插件函数

    我正在尝试在打字稿文件上使用一些科尔多瓦插件功能 但我无法构建该文件 想象一下 我想要访问设备平台和型号 有人可以帮我弄这个吗 我应该为插件的 js 文件上的每个函数创建接口吗 提前致谢 对此已有定义 https github com bo
  • 在 Dart 中克​​隆列表、映射或集

    来自 Java 背景 克隆 Dart 的推荐方法是什么List Map and Set Use of clone in Java is tricky and questionable1 2 Effectively clone is a co
  • 检测多列中的关键词并在新列中标记它们

    我有这种类型的数据 set seed 123 df lt data frame v1 sample LETTERS 1 10 5 v2 sample LETTERS 1 10 5 v3 sample LETTERS 1 10 5 v4 sa
  • Vite 构建命令挂在“模块已转换”处。在Vue 3.3.4、Vite 4.3.8环境下

    您好 我目前正在使用 Vue 3 3 4 Vuetify 3 2 5 和 Vite 4 3 8 开发一个项目 当我运行 vite build 命令时 该过程似乎挂起并且未完成 最后的输出我看到的是 679 modules transform
  • 应该如何将 F# SqlDataConnection TypeProvider 与 App.Config 文件一起使用?

    我正在使用类型表达式 type dbSchema SqlDataConnection
  • 我可以定位 .net 的(表单)消息框或通用对话框吗?

    我试图获得父窗体的中心 而不是屏幕行为的中心 传入父窗体似乎只能控制窗口的所有权 这些类是密封的 因此我不知道如何执行任何 WinProc 技巧 重写类并不是一个有吸引力的选择 还有其他想法吗 正如 HTH 上面所解释的 有一些丑陋的方法可
  • spring data elasticsearch如何使用offset和limit进行查询

    spring data elasticsearch如何使用offset和limit进行查询 我想使用偏移量和限制参数来查询页面 但我找不到方法支持 例如 queryBuild withPageable PageRequest of page
  • 为4000万条记录的表添加多列主键

    我正在维护一个数据库 该数据库存储不同网络之间的数据传输信息 本质上 每次数据传输都会被记录下来 并在每个月末运行一个 perl 脚本 将日志文件加载到数据库的表中 我没有设计 Perl 脚本或数据库模式 这是在我开始从事这个项目之前完成的