什么是 PostgreSQL?
Scrapeless Google Search API 返回可由应用验证并存入 PostgreSQL 的结构化搜索数据。
PostgreSQL 是一个开源的对象关系型数据库系统,它使用 SQL 来定义、查询和更改数据。它将记录组织到带类型的表中,并支持关系、约束和事务。应用程序利用这些能力在支持跨相关实体查询的同时,保持关于数据的规则不被破坏。
对于一个网页数据应用,PostgreSQL 可以保存被接受的观测数据以及赋予它们意义的上下文。例如,一个搜索结果隶属于一个查询、一场采集运行以及一个特定的来源配置。关系型设计将这些关系显式化,而不是让每个使用方都从一份无差别的导出数据中自行重建它们。
表为记录提供统一的结构
表定义列及其类型,使得各行可以被一致地解释。查询标识符、观测时间戳和结果位置代表不同类型的值。选择合适的类型有助于数据库拒绝部分无效输入,并使查询能够使用与这些值相匹配的操作。
将具有不同身份的实体分开建模。一个被跟踪的查询可以在任何采集运行之前就存在。一场采集运行可以产生多行结果,也可以在没有被接受结果的情况下结束。将查询、运行和结果分开建模,使数据库即使在应用将它们一起展示时也能保留这些区别。
主键在其所属表中标识一行。外键可以在数据库约束下将一行连接到一个相关实体。这些机制表达了应用所依赖的关系,但选择合适的键仍然是建模决策。一个新生成的标识符并不会自动防止重复的业务观测。
对于搜索监测,要定义是什么使一次观测具有唯一性。如果国家、语言、设备上下文或采集范围不同,仅靠查询文本可能不够。一个稳定的查询配置标识可以表示这些上下文,而运行标识表示一次特定的观测尝试。使确切的维度与实际使用的来源输入保持一致。
约束将假设变成存储规则
数据库约束在存储边界上强制执行选定的性质。必需的来源标识可以被要求为非空,业务标识可以被要求唯一,而某种关系可以要求存在相应的父行。这些规则即使在多条应用路径写入数据时,也能防止部分不一致。
约束应当描述持久的领域规则,而不是对来源当前结构的猜测。要求每条观测都必须有价格的规则,会拒绝那些价格不可用但合法的页面。更清晰的设计是将被接受且有价格的观测与明确的“不可用”或“被拒绝”的结果分开。
在 SQL 查询中,缺失值也需要被谨慎解释。未知值不同于数值 0 或空字符串。报表逻辑应保持这种区别,这样不完整的采集就不会被当成有数据支撑的缺失。数据库可以存储这种区分,而应用决定如何呈现它。
文本标识需要自己的策略。外观相似的字符串可能具有不同的底层 Unicode 表示。 Unicode 规范化形式 解释在比较文本时可能重要的规范表示。要有意识地应用规范化,并在确切的来源证据很重要时保留原始显示值。
事务协调相关的数据库更改
事务在一个定义好的提交边界内将多项数据库更改归为一组。对于一场采集运行,这可以意味着将被接受的结果行写入并更新运行完成状态,作为一个有意设计的数据库工作单元完成。若缺乏清晰边界,应用可能会显示一场“已完成”的运行,而其结果行却只被部分存储。
PostgreSQL 使用 多版本并发控制 通过数据版本来管理并发访问。事务隔离级别会影响在其他操作更改数据库时,本次操作能观察到什么。应当根据一致性需求来选择隔离行为,而不是将所有并发写入视为等价。
数据库事务并不会把远程采集请求纳入同一原子操作。来源服务可能在本地进程尚未提交其行时就已经完成了工作。要设计稳定的采集标识和可追责的交接方式,使应用能够判断在各个系统中各自接受了什么。
在应用设计允许的情况下,将漫长的远程等待放在数据库事务之外。在等待外部页面时占用数据库资源,会使并发控制和运维诊断变得复杂。先采集并验证输入,然后对那些必须同时可见的数据库更改使用一个有意识设计的存储事务。
JSON 补充关系型列
PostgreSQL 在关系型列旁边支持与 JSON 相关的类型。当来源包含可变属性,或保留原始 API 负载有助于解释规范化记录时,这会很有用。 JSON 交换规则 定义了输入格式,而数据库和应用规则决定如何使用其中的字段。
json 类型保留输入的文本表示,而 jsonb 存储适合处理与索引的分解表示。如果你需要保留精确的空白字符、对象键顺序或重复键,这种差异就很重要。不要将规范化的表示误认为是响应字节的精确归档。
将稳定且被频繁查询的字段提升为显式契约。用于连接的结果 URL、用于历史记录的运行标识符以及用于报告的观测时间,不应仅仅因为可以使用 JSON 存储就仍然隐藏在不一致的负载键之后。
使用原始有效负载作为支持性证据,而不是作为唯一的数据模型。消费者不应各自独立决定如何解释缺失的结果字段或排序类别。共享的公认模式可以降低这样一种风险:两个仪表盘会从同一存储响应中得出不同的业务结论。
一种保留上下文的搜索观测模型
搜索观察模型应分别保留查询配置、集合结果以及结果身份。 无抓取的 Google 搜索 API 提供结构化的搜索数据,而应用程序则决定哪些字段满足其报告契约。 无抓取的 Google 搜索 API 功能 描述源所支持的角色,并且在定义该输入边界时应进行检查。
想象一个团队正在监控特定市场中的公共品牌查询。查询配置会记录预期的查询以及支持的来源设置。运行记录会存储数据收集发生的时间以及其响应是否被接受。然后,结果记录会引用该次运行,并保留团队分析所需的字段。
已接受的空结果集需要与被拒绝或不完整的响应进行不同的处理。如果两者都变成没有子行的运行,报告以后将无法区分它们。显式存储结果状态,并要求报表查询在解释缺失行时使用该结果状态。
结果位置也需要一个定义。不同的源类别可能没有一个可比较的排序。要保留源类别和预期的位置信息含义,而不是将每一项简单地扁平化为一个无法解释的排名。数据库约束可以要求一个类别值,但必须由应用程序来定义它所支持的类别。
索引应遵循真实报表查询
索引支持特定的访问模式,并会增加存储和写入开销。先从应用必须回答的查询入手:某个查询配置下最近被接受的运行、选定观测之间的差异,或与已知源 URL 关联的结果。
索引字段的顺序和组合应当反映这些查询。一个按配置进行过滤并按观测时间排序的集合,与一个在载荷中搜索任意文本的查询,其需求是不同的。在假定任意相关列上的索引就能解决问题之前,先使用具有代表性的数据检查查询计划。
保留策略也会影响索引和表的设计。如果历史观测数据持续增长,需要规划如何删除旧分区或记录,以及下游报表如何保持其含义。删除一次运行却保留其子行,或者移除旧的源上下文却保留无法解释的指标,都会破坏模型最初要维护的那些关系。
这次讨论 为收集的网页数据提供存储选项 提供了更广泛的存储选项视角。选择 PostgreSQL,是因为它的数据模型和运维能力适合该应用,而不是因为每个集合都需要相同的归宿。在做出决定时,除了查询性能外,还要同时考虑备份、恢复、维护和访问管理。
存储完整性与源真实性是相互独立的
PostgreSQL 在强制关系一致性的同时,仍可能存储事实层面错误的源解释。一个类型完全正确的价格仍然可能指向错误的产品,而一个语法上有效的结果 URL 也仍然可能来自针对另一个市场的响应。对数据源的接纳与否始终是应用自身的责任。
在已接受的记录中保留来源信息。记录采集上下文、抽取版本以及相关的来源标识,以便分析人员能够解释异常值。避免仅仅因为数据库可以存储它们而在原始有效负载中保留不必要的机密或敏感内容。
从数据库操作中单独收集预算来源。 无爬取定价 在规划搜索收集频率和范围时,每小时存储一份报告并不能证明该来源是每小时新观测到的,因此,报告层应显示底层已接受观测结果的时间,而不仅仅是其自身的生成时间。
结论
PostgreSQL 将带类型的关系型存储与事务、约束以及 JSON 支持结合在一起。当集合需要清晰的关系和可靠的报表语义时,这些能力就非常有用。先定义查询和观测的标识,将空结果和未知结果分别保留开来,并在显式的边界内提交已接受的记录。这样,数据库就可以支持那些其取值及其缺失都具有可解释含义的报表。
准备好一致地存储搜索观测结果了吗?
在将搜索结果转换为报告表之前,先定义查询标识、观测时间和数据库约束。
今天注册即可获得 5 美元免费额度 — 无需信用卡.
领取您的 $5 额度 →常见问题解答
问:Postgres 和 PostgreSQL 是不同的数据库吗?
Postgres 是 PostgreSQL 的常用简称。在选择文档或依赖项时,请使用完整的项目名称,以免将相关服务或扩展误认为是核心数据库。
问:PostgreSQL 只存储文本表吗?
PostgreSQL 支持带类型的关系列以及额外的类型,包括与 JSON 相关的类型。请根据应用程序所需的操作和完整性规则来选择类型,而不是将每个值都存储为字符串。
问:一笔交易会验证抓取的内容吗?
事务在其配置的隔离行为下,将数据库操作作为一个整体进行控制。它并不决定远程页面是否包含正确的价格、标题或结果集;那类校验应在写入存储之前或与写入存储并行完成。
问:原始 JSON 是否应该取代关系型列?
原始 JSON 可以保留来源细节,而关系型列则使对稳定字段的约束和查询更容易。将原始负载与已接受的类型化字段结合起来,通常比只选择其中一种表示方式更能为应用程序提供更清晰的契约。