我似乎无法找到任何人在网上做这个的例子,所以我想知道是否有这样的原因(或者我没有使用正确的搜索条件)。甚至可能已经有一个我不知道的术语?
为了节省数据库存储空间以便定期重复发生字符串,我正在考虑创建一个名为 unique_string 的MySQL表。它只有两列:
然后,数据库中任何位置的任何其他表都可以使用INT列而不是VARCHAR列。例如,名为浏览器的varchar字段将改为名为 browser_unique_string_id 的INT字段。
我不会将此用于性能重要的任何事情。在这种情况下,我使用它来跟踪每个页面请求的详细信息(记录Web统计信息)和内部网上用户操作的“审计试验”,但也可能是其他事情。
我也知道SELECT查询会很复杂,所以我并不担心。我很可能会编写一些代码来生成查询以返回“真正的”字符串数据。
思考?我觉得我可能会忽略一些明显的东西。
谢谢!
答案 0 :(得分:1)
我已将此结构用于类似的应用程序 - 跟踪Web日志的URI。在这种情况下,数据库是Oracle。
性能问题并不是最小的。随着数据库的增长,有数千万个URI。因此,在INSERT期间识别正确的字符串是一项挑战。我们通过在hadoop中构建大部分更新逻辑来处理这个问题,因此数据库表实际上只是hadoop表的副本。
在常规数据库中,您可以通过构建索引来解决这个问题,正如您在问题中所建议的那样。并且,索引解决方案可以很好地满足您的可用内存。实际上,对于索引来说,这是一个相当简并的情况,因为您实际上只需要索引而不是基础表。我不知道mysql或SQL Server是否认识到这一点,尽管柱状数据库(例如Vertica)应该。
SQL Server有另一种选择。如果将字符串声明为VARCHAR(max),则它不会存储与其余数据不同的单独数据页。在全表扫描期间,如果查询中未引用该列,则无需在内存中加载其他页面。
答案 1 :(得分:0)
这是数据库中非常常见的设计模式,其中数据的基数与其链接的事务表相比相对较小。查询不会非常复杂,只是对查找表的简单连接。您可以在查找表中包含多个字符串,以及通常重复的其他信息。您只需normalizing您的模型即可删除重复数据。
示例:
请求表:
Date
Time
IP Address
Browser_ID
浏览器表:
Browser_ID
Browser_Name
Browser_Version
Browser_Properties
答案 2 :(得分: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
如果您担心应该是数据完整性,那么通常会通过查询将数据定期写入一组单独的表(或单独的数据库)并将其用于查询来规范化此数据。