【问题标题】:What's the fastest way to check if a username is available with a huge dataset?检查用户名是否可用于庞大数据集的最快方法是什么?
【发布时间】:2019-09-20 07:35:21
【问题描述】:

我正在寻找最快/最有效的方法来搜索给定用户名是否可以从一组数千万个用户名中获得。目前我正在使用一个普通的 MySQL SELECT 查询,它运行每个按键,但我对性能不满意。我正在使用索引、分区等,我知道 MySQL 可以优化得非常快,但我也知道有更好的解决方案。

那么什么是最快的用户名搜索:

  • Redis EXISTS 命令
  • 弹性搜索
  • 别的东西

例如:Gmail 如何在注册时搜索数十亿个电子邮件地址。脸书是如何做到的?我假设他们不只是运行 SQL 查询。

我正在为 PHP 应用寻找实用的解决方案。

现在我只使用一个非常基本的选择:

SELECT username FROM users WHERE username = $username LIMIT 1

用户名列上有唯一索引

【问题讨论】:

  • 对唯一索引的 SQL 查询有什么问题?如果操作正确,它应该是 O(logN)。
  • @Dharman 根据所采用的索引方法,它甚至可能比这更少。
  • 你为什么要检查每一次按键?
  • 如果您的查询需要 150 毫秒来运行您的表没有正确索引,您的服务器没有正确调整,或者您的硬件严重不足以完成手头的任务。我拥有拥有数十亿条记录的生产系统,并且测试UNIQUE 密钥的存在时间几乎为零。某些数据库(如 Postgres)为您的数据提供多种索引方法,您可以选择在您的用例中表现最佳的一种。
  • @tomschmidt 您使用的是哪种查询?存在查询应该比普通选择花费更少的时间;它可以在第一场比赛停止,而不是继续收集所有比赛。另外,根据我对php的有限了解;如果您正在检查每个按键,那么您实际上并没有使用 php。

标签: php mysql redis


【解决方案1】:

我同意您应该尝试将其全部保存在 RAM 中(例如 Redis)。

但是,如果您不想一路走下去,我会执行以下操作:将列表存储在较慢的地方(例如 S3 或 SQL 数据库)。接下来,从该列表中创建一个 Bloom 过滤器(维基百科上有关于此的内容,并且您可以使用一个漂亮的 Redis 模块 - https://oss.redislabs.com/redisbloom)。

现在,BF tell 永远不会给您一个假阴性,因此您可以有效地检查用户名是否可用。但是,有时,BF 会报告用户名不可用(误报),而您已决定是否可以接受。

【讨论】:

    【解决方案2】:

    将列表加载到关联数组中。测试密钥的存在。完毕。如今,“数千万”并不是很多数据。它适合 RAM。

    如果您内存不足并且不介意误报的可能性很小,您可以使用 SHA2-256 哈希值而不是完整值。这些只是 40 字节的十六进制编码,20 字节的原始格式。检查哈希键是否已被索引很简单,在许多情况下甚至 O(1) 时间。

    请记住,这仅在您处理超过每秒 1000 个查询的峰值负载时才有意义。不要过早地优化它。大多数数据库可以在基本上零时间内完成用户名测试,这甚至不难,并且每秒进行一千次测试不会破坏您的服务器。

    如果您确实有可衡量的性能问题,那么您可以随时探索索引选项。 MySQL supports different index typesBTREEHASH。它们的表现不同。

    【讨论】:

    • 我考虑过;但是:检查数组中是否存在值会比数据库引擎进行搜索更快吗?我知道过早的优化,但目前此检查需要 100-200 毫秒,我需要将其降低到接近 1 毫秒或更短。
    • 据我所知,InnoDB 只支持 Btree 索引,我正在使用 InnoDB。
    • 它仍然不应该这么慢。这可能是DBA site 的问题。
    【解决方案3】:

    您的示例提到了使用高端系统的公司。显然没有任何系统可以做到这一点,原因如下:

    让我们假设一家巨大的公司如何处理数十亿用户中的任何用户名:

    有一个服务,可能是用 C 写的,甚至不是 C++

    部署在 Unix 或 Linux 集群中

    还有另一个服务充当第一个检查每个例如的健康检查器。第二个标准用户名和密码

    服务将所有数据(通常是用户名和密码)加载到内存中

    当数据源发生变化时,调用它来采用变化,这是从数据源触发的

    当需要调用数据时(我们的例子),有 2 次(最少)异步调用两个健康检查器副本(以避免服务死延迟)主服务处于活动状态

    当任何健康检查器回复 ok 时,就会调用(检查器的)主服务,并验证是否请求了用户名和/或密码。

    然后调用者继续根据回复。

    最后,任何尽可能接近此的解决方案都可以快速工作。像上面提到的redis这样的内存'db'有点接近 - 考虑到差异,有点意味着足够接近。如果一家大型公司获得 10 分的绩效,而一个简单的网站获得 8-9 分的绩效,使用类似的做法遵循相同的原则并根据每个公司规模调整成本,那么我认为这是一个成功的选择。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-25
      • 1970-01-01
      • 1970-01-01
      • 2011-11-26
      • 2023-03-16
      • 2011-07-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多