优化生成的字符串以存储到数据库中

时间:2013-03-27 21:23:05

标签: mysql database sqlite postgresql indexing

我有一个64位整数时间戳和一个Sting用户名,可以组合成一个字符串并最终存储到数据库列中。抛开为什么我不能将它们存储在具有适当类型的单独列中,我的问题是如何将它们组合以从底层数据库中获得更好的性能。那将是sqlite,PostgreSQL或MySQL,还不确定。

我想象他们会使用b-tree作为索引,并且像(timestamp-username)那样连接会很糟糕,因为时间戳通常总会进展,而树需要经常进行平衡。 username-timestamp应该要好得多,但每个用户记录仍会随着每个新条目而增加。 我当时还想把时间戳与反向的比特顺序放在一起。

我还能做什么?一些聪明的xor或其他什么?什么是合理最佳架构?通过请求确切生成的字符串,没有范围等来访问数据。

唯一的要求是在生成的字符串和源数据之间以两种方式进行相对快速的转换。

更新:请大家好,我正在寻找信息,哪种字符串更适合存储为数据库的主键(sqlite,mysql和postgresql之一)。也许答案是无关紧要,或者取决于数据库引擎。我没有使用我正在使用的架构或缓存解决方案的特定问题。我只想问是否有任何改进空间以及如何改进。我会感谢一些主题答案。

UPDATE2:伟大的答案对我来说仍然不是最终的: does incremented column makes the b-tree index on the column unbalanced? https://stackoverflow.com/a/2362693/520567

2 个答案:

答案 0 :(得分:1)

你的问题有一个矛盾,你指定你不能拆分它们并将它们存储在不同的列中,但是你要说的是分开索引这两个部分 - 如果不拆分它们就不能这样做。

我可以看到你真的有两个选择:

  1. 将它们存储在不同的列中
  2. 散列输出以降低索引内存占用
  3. 理想情况下,如果您始终以相同的顺序一起搜索它们,则应将它们存储在两列中并创建复合索引。在这种情况下,如果不首先提供更多信息,很难给出准确的建议 - 但是通常用户名,时间戳在符合每个用户的情况下会有逻辑意义,或者如果您想通过时间戳查询则反转它。如果您需要搜索其中一个,也可以在每个列上创建索引。

    哈希生成的字符串

    INSERT INTO table (crc_hash_column, value_column_name)
    values (CRC32(@generated_value), @generated_value)
    

    会将大小减小到32位整数(每行只有4个字节的索引),远小于所需的equifivant VARCHAR或CHAR索引空间。

    如果采用这种方法,那么你应该采取措施避免碰撞,因为它会发生生日悖论,并且更有可能随着数据集的增长而增加。即使存在冲突,额外过滤仍会在给定索引大小的情况下产生更高的性能。

    SELECT * FROM table
    WHERE crc_hash_column = CRC32(@search_value) 
    AND value_column_name = @searchvalue
    

    使用散列会导致更多的CPU周期 - 但是CRC32散列非常快,所以即使你每次搜索都需要重新进行这种额外的工作,这对于索引大量数据所带来的好处也是微不足道的。

    一般来说,我更喜欢第一种选择,但在不知道你的用例的情况下几乎不可能推荐它。

    您应该分析这两个选项,看看它们是否符合您的要求。

答案 1 :(得分:0)

你说你不能将它们保存在单独的列中(你甚至无法设置一个具有1:1关系的新表/使用触发器将数据镜像到物化视图/用视图替换现有表一个更正的表结构???? !!!!)意味着任何解决方案将是一个丑陋的黑客。

是的,数据变化多少以及结构如何影响更新效率。然而,索引的目的是加快检索速度 - 您没有向我们提供有关如何访问数据/如何更改数据的信息。

  

我在考虑将时间戳与位的反向顺序放在一起

为什么呢?这更有可能加速索引碎片而不是降低索引碎片。

MariaDB支持虚拟列 - 以及虚拟列上的索引,因此您可以执行愚蠢的操作,例如将规范化规则抛出窗口 - 但如果您无法解决模式中的一个小问题,那么替换DBMS可能会赢得'也是一个非常实用的解决方案。

坦率地说,如果值得花时间和金钱为问题制定一个糟糕的解决方案,而这个解决方案的成本与适当的解决方案一样多,并且很可能会产生未来的成本,那么选择糟糕的解决方案就会浪费时间和金钱。