2

我似乎在网上找不到任何人这样做的例子,所以我想知道这是否有原因(或者我可能没有使用正确的搜索词)。甚至可能已经有一个我不知道的术语?

为了为定期重复出现的字符串节省数据库存储空间,我正在考虑创建一个名为unique_string的 MySQL 表。它只有两列:

  1. “id ”:INT:PRIMARY_KEY 索引
  2. “字符串”:varchar(255):唯一索引

然后,数据库中任何位置的任何其他表都可以使用 INT 列而不是 VARCHAR 列。例如,名为browser的 varchar 字段将改为名为browser_unique_string_id的 INT 字段。

我不会将它用于性能重要的任何事情。在这种情况下,我使用它来跟踪每个页面请求的详细信息(记录 Web 统计信息)和对 Intranet 上的用户操作的“审计试验”,但其他事情也可能如此。

我也知道 SELECT 查询会很复杂,所以我并不担心。我很可能会编写一些代码来生成查询以返回“真实”字符串数据。

想法?我觉得我可能在这里忽略了一些明显的东西。

谢谢!

4

3 回答 3

1

我已经将此结构用于类似的应用程序——跟踪 Web 日志的 URI。在这种情况下,数据库是 Oracle。

性能问题不是最小的。随着数据库的增长,有数千万个 URI。因此,仅在 INSERT 期间识别正确的字符串是具有挑战性的。我们通过在 hadoop 中构建大部分更新逻辑来处理这个问题,因此数据库表本质上只是 hadoop 表的副本。

正如您在问题中所建议的那样,在常规数据库中,您可以通过构建索引来解决此问题。而且,索引解决方案可以很好地满足您的可用内存。实际上,这对于索引来说是一种相当退化的情况,因为您实际上只需要索引而不需要基础表。我不知道 mysql 或 SQL Server 是否可以识别这一点,尽管列式数据库(例如 Vertica)应该。

SQL Server 有另一种选择。如果您将字符串声明为 VARCHAR(max),则它不会与其余数据存储单独的数据页。在全表扫描期间,如果查询中未引用该列,则无需在内存中加载附加页。

于 2012-05-22T14:46:17.350 回答
0

这是数据库中非常常见的设计模式,其中数据的基数与其链接的事务表相比相对较小。查询不会很复杂,只是对查找表的简单连接。您可以在查找表中不仅包含一个字符串,还可以包含通常重复的其他信息。您只是对模型进行规范化以删除重复数据。

例子:

请求表:

Date    
Time   
IP Address    
Browser_ID  

浏览器表:

Browser_ID
Browser_Name
Browser_Version
Browser_Properties
于 2012-05-22T14:09:59.490 回答
0

如果您计划实时记录数据(而不是批处理作业),那么您希望确保将记录写入数据库的时间尽可能快。如果您正在同步记录,那么显然记录创建时间将直接影响 http 请求完成所需的时间。如果这是异步的,那么缓慢的记录创建时间将导致瓶颈。但是,如果这是批处理作业,那么只要您可以在下一个批处理运行之前自信地创建所有批处理记录,那么性能就无关紧要了。

为了减少创建您真正想要展平数据库结构的记录所需的时间,您当前的伪查询可能看起来像

SELECT @id = id from PagesTable
WHERE PageName = @RequestedPageName

IF @id = 0
THEN 
  INSERT @RequestedPageName into PagesTable
  @id = SELECT @@IDENTITY 'or whatever method you db supports for              
                          'fetching the id for a newly created record
END IF

INSERT @id, @BrowserName INTO BrowersLogTable 

在平面结构中,您只需要 1 INSERT

如果您担心数据完整性,那么您通常会通过定期查询将这些数据写入一组单独的表(或单独的数据库)并将其用于查询来规范化这些数据。

于 2012-05-22T14:23:18.233 回答