1

从客户端机器我必须每 30 秒获取 600*10 条记录,它应该存储在 DB 中。我有大约 600 个 ID,每个 ID 有 10 个参数,所以总共是 6000。所以我正在考虑一个表结构最低性能问题。

第一个想法

列名将是 1 到 600 范围内的 id,行将是如下参数

1 2 3 4 5 6 7 8 9 9..............598 598 599 600
a b c d e f g h i o..............d    d   f   h
g m m k s l l j j k..............u    j   j   j
             .
             .
             . 10 parameters
             .
             .
a d g h j k l l l y..............k    l   l    l      
a b c d e f g h i o..............d    d   f   h
g m m k s l l j j k..............u    j   j   j
             .
             .
             . 10 parameters
             .
             .
a d g h j k l l l y..............k    l   l    l      
a b c d e f g h i o..............d    d   f   h
g m m k s l l j j k..............u    j   j   j
             .
             .
             . 10 parameters
             .
             .
a d g h j k l l l y..............k    l   l    l    

因此,每 30 秒,我将作为新行(相应参数)插入数据库。

第二个想法

我将为相应的参数制作 10 个不同的表,为 ids 制作一个表,它是与其他 10 个表(参数表)的外键链接的主键

如果您有任何其他想法,那么也非常受欢迎。

我现在使用 ms sql server 但数据库无关紧要(我也可以使用其他数据库)

4

2 回答 2

1

我相信您需要临时表概念。您应该做的是检索所有外部数据源并将它们从原始数据源完全加载到临时表中。之后,您将此数据加载到您的事务结构中。在这个概念中,您总是区分数据结构stagingtransactional数据结构。顺便说一句,这通常是更大的ETL概念(提取/转换/加载)的一部分。

我将描述一种进行分期的“风味”:

  • 分析原始形式的数据

    它可以是 CSV、Excel、分隔或格式化文件、另一个数据库或其他任何东西。您必须列举有限数量的来源和结构才能进行分期。稍后再介绍其他资源是可以的,但首先要集中精力,比如说,少数几个。写下每个表/字段的名称 - 从一开始就明确。写下/记录每个表格/字段的格式——这将使您更容易编写代码,并在以后的生产中查找数据错误——例如,内容过长的文本字段。

  • 创建临时表结构

    您可以在单独的数据库、单独的架构甚至事务数据所在的相同数据库/架构中执行此操作。数据库/模式分离主要是出于管理目的而引入的,例如限制数据库增长、分析传入数据的用户权限等。它对于“关注点分离”也很有价值。因此,将您在上一步中写下的结构并从中创建表格。如果我出于某种原因必须操作行数据,我喜欢向每个数据源添加另一个标识(序列)列,以便轻松识别加载的原始数据行。

  • 引入额外的表格/列

    这些是计算列、批号标识表、批号列等。您认为需要添加到暂存表以使其适用于暂存过程的每个开销。例如,当您在一天中多次导入数据并且执行从暂存到事务数据的数据加载的过程每天运行一次时。然后在开始每次数据导入之前,在表中创建批号,并在已添加到每个临时表的附加列中Batch使用该编号。BatchNumber然后,您的数据加载过程将批量加载数据。

  • 添加约束

    只有当您知道自己在做什么时,您才应该采取这一步。对临时表有约束的一个原因是您根本不想看到不一致的源数据。通常,这不是必需的,您希望导入所有外部数据以进行暂存。

  • 创建数据转换/加载程序

    这里我指的不是 SQL Server 存储过程,而是暂存数据所需的逻辑过程。原始存储过程、SSIS 包、外部进程、SQLCLR 程序集等的实现可能会有所不同。底线是您必须将数据从暂存表中的格式 A 转换为事务表中的格式 B。通常我在临时表上编写 SQL 查询并填充事务表。您必须涵盖转换失败的情况:如果原始数据中的日期时间根本不是日期时间怎么办?如果您不期望空数据怎么办,您应该将其替换为 NULL 吗?例如,父子行,孤行之间的数据不一致怎么办?顺便说一句,这一步是ETL 过程的转换部分。

    最后,应该将此数据插入到您的事务结构(ETL加载部分)中。

    当你实现它时,你需要试一试——获取一些数据源并尝试通过转换运行它。如果其中至少有一个失败,这很好,因为您发现了一些意想不到的东西,并且没有尝试用它来填充生产表;)

我没有涵盖为 ETL 流程创建计划、数据导入失败的警报和报告、数据清理、执行匹配/合并等。此外,我没有在这里介绍一些实现细节,比如您是否应该删除(或更好地截断)您在 ETL 过程之后从暂存表中导入的数据,或者让它留在那里以进行某种导入存档。这可能是一个相当复杂的过程,而正确的工作概念/工具可以使它更容易。

高温高压

于 2013-08-13T07:51:36.733 回答
1

一般来说,我建议设计数据库以尽可能接近地对问题域进行建模,并且只在可以证明自己有问题时才担心性能。

根据您的问题,我无法处理基础数据 - 每 30 秒 10 条记录,600 列似乎是最好的描述。因此,首先创建一个模拟该模型的表 - 几乎是“选项 1”。

创建一个测试环境,并将其充满数据,这样您就可以重现生产规模的性能问题。10 条记录 * 120 / 小时 * 24 小时 = 29K/天;推 6 个月左右的时间(谷歌 DBMonster 可以帮助您创建测试数据的工具;Redgate 也有一个产品)。

运行您的插入、选择以及针对此数据运行的任何其他查询,并调整所有内容。如果这不起作用,请购买更大的硬件。只有当这不起作用时,您才应该考虑不为域数据结构建模的解决方案 - 维护的长期成本和让开发人员加快您的奇异解决方案的速度通常比硬件成本高出一个数量级.

如果达到这一点,可以考虑的选项:

  • OzrenTkalcecKrznaric 建议使用临时表。在此模型中,您的插入语句每 30 秒将数据转储到针对写入进行了优化的表中;您有第二个过程(例如,定时批处理)将数据转换为目标格式。引入了数据的复杂性和时间问题,但通常会使插入速度更快。
  • 对插入使用消息队列系统。这释放了您的客户端代码,并为将数据移动到数据库提供了一个可预测、可管理、理论上防弹的过程。同样,额外的复杂性 - 更多的移动部件 - 和时间问题,但这是银行等高吞吐量系统使用的架构。
于 2013-08-13T07:55:09.007 回答