如何通过邮政编码存储/查询用户元数据

时间:2017-02-22 19:23:13

标签: mysql latitude-longitude zipcode bigdata

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

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

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个邮政编码,几百个服务和几千个用户,并且没有用户可以在同一个邮政编码中为同一服务的其他用户提供相同的优先级。

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

而且,也想知道重组这些数据的任何建议。

我在这里看到的问题是随着用户群的增长,service_priority表将变得庞大,理论上每个用户大45000行,尽管在实践中可能只有10000行更大。

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

1 个答案:

答案 0 :(得分:1)

切换到InnoDB。

zip_code表可能应该有PRIMARY KEY(zip),除非您确实需要给定zip的多行。

"在同一邮政编码中,没有用户可以拥有与同一服务的另一个用户相同的优先级" - 可以通过

强制执行
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。
  • 中间查询的重点是找到附近的拉链。查看我添加的标签,找到许多问题,讨论如何做到这一点。
  • 外部查询然后根据用户和服务过滤结果。
  • 最后,选择优先级最高的行。