3

我在日志搜索速度和磁盘大小方面遇到问题。它非常大,大约有 2.2 亿行和 25 GB 的磁盘大小,需要几分钟才能获取一些选择。

它是如何工作的?日志使用Sql Anywhere保存在数据库中,目前版本9,很快将迁移到11(我们尝试到12,但由于一些驱动程序和一些问题,我们回到了11)。

该日志包含两个表(名称更改为英文,以便这里的人能够理解):

日志表

Id、DateTime、User、Url、Action 和 TableName。 Action 是 used 所做的:插入/删除/更新 TableName 是数据库中的哪个表受到影响。

日志表字段

Id、LogTable_Id、FieldName、NewValue、OldValue。 LogTable_Id 是来自 LogTable 的外键。FieldName 是 DB 中表的字段。

重要的是要注意 NewValue 和 OldValue 是 varchar 类型。因为它记录了其他表(datetime、int 等)中的各种字段。

为什么它是这样制作的? 因为我们必须记录所有重要的事情。该系统是由交通机构部门制作的(我不知道它是否用正确的英语拼写,但现在你可以知道这是关于什么的),有时他们需要某种随机报告。

到现在为止,我们只做了一些 SQL 选择来制作我们的报告。但是,即使过滤了日期时间,也需要几分钟才能完成。不是经常抱怨的问题。

但是他们要求越来越多的报告表明,有必要在软件中创建一个带有漂亮和美观报告的功能。由于我们永远不知道他们的需求,我们必须回去记录并挖掘数据。

请求的某些信息仅在日志中。(例如,什么用户不正当地向某人提供了车辆的使用权)

到目前为止提出的一些想法:

想法 1: 我做了一些研究,并被告知使用 NoSql 使用CouchDB。但是我读到的很少,我觉得 NoSql 不能解决我的问题。我不能争论为什么没有经验。

想法 2: 将日志表与数据库或机器物理分离。

想法 3: 从每个表创建一个带有版本字段的镜像以保留历史记录。

如果需要,我想要一个宏优化或架构更改。

4

2 回答 2

1

这似乎是一个非常标准的审计表。我不确定您是否需要为此使用 NoSQL 解决方案。大多数 RDBM 可以轻松处理 2.2 亿行。

似乎最大的问题是表结构。通常,您将表格展平以提高记录速度并对其进行规范化以提高报告速度。正如你所看到的,这些是相互矛盾的。

如果您使用的是 MS SQL 之类的东西,您可以构建一个单一的平面表来记录性能,然后在其上构建一个简单的 Analysis Services 多维数据集。

另一种选择是仅优化报告,假设您可以保持足够的日志记录吞吐量。为此,您可能需要创建如下结构:

创建表 LogTable (
  LogTableID int 身份(1,1),
  表名 varchar(100),
  网址 varchar(200)
)

创建表 LogUser (
  LogUserID int indentity(1,1),
  用户名 varchar(100)
)

创建表 LogField (
  LogFieldID int identity(1,1),
  字段名 varchar(100),
)

创建表 LogData (
  LogDataID bigint identity(1,1),
  LogDate 日期时间,
  LogTableID int 引用 LogTable(LogTableID),
  LogFieldID int 引用 LogField(LogFieldID),
  LogUserID int 引用 LogUserID(LogUserID),
  Action char(1), -- U = 更新, I = 插入, D = 删除
  旧值 varchar(100),
  新值 varchar(100)
)

这应该仍然足够快以快速记录数据,但为报告提供足够的性能。索引设计也很重要,通常按照基数递增的顺序进行,例如 LogData(LogTableID, LingFieldID, LogDate)。您还可以通过分区来实现并行查询。

于 2012-01-14T08:45:33.743 回答
1

添加适当的索引将是您可以做出的最大改进。你没有提到有任何索引,所以我假设你没有任何索引。那会使它变得非常缓慢。

例如,将查询限制在 DateTime 的特定范围内根本没有帮助,除非您在 DateTime 上有索引。在没有索引的情况下,数据库仍然需要访问几乎所有 25GB 的数据才能找到在正确时间范围内的少数行。但是使用索引,它可以快速识别出您关心的时间范围内的少数行。

通常,您应该始终询问您的数据库它使用什么计划来执行耗时过长的查询。我对 Sql Anywhere 不是特别熟悉,但我知道它有一个 Plan Viewer 可以做到这一点。您想要识别大型顺序扫描并将索引放在这些字段上。

I doubt you would see a measurable improvement from breaking up the table and using integer foreign keys. To the extent that your queries touch many columns, you'll just end up joining all those tables back together anyway.

于 2012-01-18T06:23:40.993 回答