如何通过邮政编码 store/query 用户元数据

How to store/query users meta-data by zip code

我有一个复杂的问题,但我没有详细说明,而是将其简化为以下内容。

假设我们正在尝试构建一个系统,该系统的用户可以在每个邮政编码的基础上申请各种服务的优先级。该系统将有四个 table 像这样...

CREATE TABLE `zip_code` (
  `zip` varchar(7) NOT NULL DEFAULT '',
  `lat` float NOT NULL DEFAULT '0',
  `long` float NOT NULL DEFAULT '0'
  PRIMARY KEY (`zip`,`lat`,`long`),
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

CREATE TABLE `user` (
  `user_id` int(10) NOT NULL AUTO_INCREMENT
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

CREATE TABLE `service` (
  `service_id` int(10) NOT NULL AUTO_INCREMENT
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

CREATE TABLE `service_priority` (
  `user_id` int(10) NOT NULL',
  `service_id` int(10) NOT NULL',
  `zip` varchar(7) NOT NULL,
  `priority` tinyint(1) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

现在再假设我们有 45000 个邮政编码、几百个服务和几千个用户,对于同一邮政编码中的同一服务,任何用户都不能拥有与另一用户相同的优先级。

我需要一个查询,如果给定一个特定的邮政编码、半径、服务和 user_id 将 return 该服务半径内所有其他邮政编码的最高可用优先级.

而且,还想知道有关重组此数据的任何建议。

我在这里看到的问题是随着用户群的增长,service_priority table 会变得很大,理论上每个用户都会增加 45000 行,尽管实际上可能只有 10000 行行更大。

我可以做些什么来缓解这些问题?

切换到 InnoDB。

zip_code table 可能应该有 PRIMARY KEY(zip) 除非你真的想要一个给定的 zip 的多行。

"no user can have the same priority level as another user for the same service in the same zip code" -- 可以由

强制执行
service_priority : UNIQUE(service_id, user_id, zip)

那么您的查询可能类似于

SELECT sp.*
    FROM ( SELECT b.zip
             FROM ( SELECT lat, lng FROM zip_code WHERE zip = '$zip' ) AS a
             JOIN zip_code AS b
             WHERE ... < $radius
         ) AS z
    JOIN service_priority AS sp
    WHERE sp.zip = z.zip
      AND sp.user_id = $user_id
      AND sp.service_id = $service_id
    ORDER BY sp.priority DESC
    LIMIT 1

备注:

  • 上面的索引也是为这个查询量身定做的。
  • 最里面的查询得到一个 lat/lng 作为中心点。
  • 中间查询侧重于查找附近的 zips。查看我添加的标签以找到许多问题讨论如何做到这一点。
  • 外部查询然后根据用户和服务过滤结果。
  • 最后,选择优先级最高的行。