SQL性能搜索长字符串

时间:2012-01-12 23:53:00

标签: mysql string hash user-agent

我需要将用户代理字符串存储在数据库中,以便跟踪和比较不同浏览器之间的客户行为和销售业绩。非常简单的用户代理字符串长度约为100个字符。决定使用varchar(1024)来保存数据库中的useragent数据。 (我知道这是矫枉过正,但这就是想法;它应该适应未来几年的使用者数据,一些设备,工具栏,应用程序已经推送了500个字符。)保存这些字符串的表将被规范化(每个不同的用户)代理字符串只会被存储一次)并被视为缓存,所以我们不必一遍又一遍地解释用户代理。

典型的用例是:

  • 用户来到我们的网站,被检测为新的游客
  • 为此用户创建新会话信息
  • 确定我们是否需要分析用户代理字符串,或者我们是否对文件进行了有效分析
  • 如果我们拥有它,那么很好,如果没有,请分析它(目前,我们计划调用第三方API)
  • 将相关信息(浏览器名称,版本,操作系统等)存储在绑定现有用户会话信息并指向缓存条目的连接表中

注意:我倾向于在数据库中说“搜索”用户代理字符串,因为它不是一个简单的查找。但要明确的是,查询将使用'='运算符,而不是正则表达式或LIKE%语法。

因此,查找用户代理字符串的速度至关重要。我已经探索了一些方法来确保它具有良好的性能。由于大小原因,将整列索引是正确的。部分索引不是一个好主意,因为大多数用户代理最终都有区别信息;部分索引必须相当长才能使其值得,因此它的大小会导致问题。

所以它归结为哈希函数。我的想法是在Web服务器代码中散列用户代理字符串并运行select以查找数据库中的散列值。我觉得这样可以最大限度地减少数据库服务器上的负载(而不是让它计算哈希值),特别是因为如果找不到哈希值,代码就会转向并要求数据库再次计算插入的哈希值

散列为整数值可以提供最佳性能,但存在更高的冲突风险。我期待最多看到数千或数万用户代理;甚至100,000个用户代理也能很好地适应2 ^ 32大小的整数,只有很少的冲突,可以通过Web服务解密,而性能影响最小。即使您认为整数哈希不是一个好主意,使用32字符摘要(例如SHA-1,MD5)对于选择应该比原始字符串快得多,对吗?

我的数据库是MySQL InnoDB引擎。 Web代码将首先来自C#,稍后将来自php(在我们整合一些托管和身份验证之后)(并不是说Web代码会产生很大的不同)。

如果您认为这是一个蹩脚的选择我的哈希算法问题,请在这一点上道歉。我真的希望从之前做过类似事情的人和他们的决策过程中获得一些意见。所以,问题是:

  • 您将在此应用程序中使用哪种哈希?
  • 你会在代码中计算哈希值还是让数据库处理它?<​​/ li>
  • 在数据库中存储/搜索长字符串是否存在完全不同的方法?

2 个答案:

答案 0 :(得分:2)

您想要散列长字符串以创建在商店(缓存或数据库)中查找的令牌是一个很好的想法。我已经看到这对于非常大的字符串,并且在高容量环境中已经完成,并且它工作得很好。

“你会在这个应用程序中使用哪个哈希?”

  • 我认为加密(哈希)算法并不重要,因为您没有哈希来加密数据,您正在哈希创建一个令牌,用作查找较长值的密钥。因此,散列算法的选择应基于速度。

“你会在代码中计算哈希值还是让数据库处理它?”

  • 如果是我的项目,我会在应用层进行散列,然后将其传递给在商店内查找(缓存,然后是数据库)。

“在数据库中存储/搜索长字符串是否存在完全不同的方法?”

  • 正如我所提到的,我认为,出于特定目的,您提出的解决方案很好。

表格建议(仅限说明):

user

  • id int(11)unsigned not null
  • name_first varchar(100)not null

user_agent_history

  • user_id int(11)unsigned not null
  • agent_hash varchar(255)not null

agent

  • agent_hash varchar(255)not null
  • browser varchar(100)not null
  • agent文字不为空

关于架构的几点说明:

  • 从您的OP看起来您需要用户和代理之间的M:M关系,因为用户可能正在使用Firefox,但之后可能会在家中切换到IE9。因此需要数据透视表。

  • 用于agent_hash的varchar(255)值得商榷。 MySQL suggests使用varbinary列类型存储哈希值,其中有几种类型。

  • 我还建议将agent_hash作为主键,或者至少为该列添加UNIQUE约束。

答案 1 :(得分:0)

你的哈希想法是合理的。我实际上使用散列来加速对数百万条记录的搜索。由于每个条目的大小相同,因此哈希索引会更快。在你的情况下md5可能会很好,并可能会给你最短的哈希长度。如果您担心哈希冲突,可以添加包含代理字符串的长度。