我想存储用户访问过的城市。在个人资料页面中,将列出用户访问过的所有城市。并且将有一个功能,用户可以搜索“谁访问过该城市”(可以进行多个城市搜索)
我打算做多对多的关系。
Table Users
-----------
UserID
UserName
...
Table Cities
-------
CityID
CityName
....
Table City_Relations
-----------
UserID
CityID
在个人资料页面中,我可以运行一个简单的查询来获取城市。
select c.cityname FROM city_relations cr left join cities c on ( c.cityid = cr.cityid ) where cr.userid = 'USERID'
并在搜索页面中获取访问所选城市的用户;
select u.username FROM city_relations cr left join users u on ( u.userid = cr.userid ) where cr.cityid = 'CITYID' ( there may be cr.cityid = '1' or cr.cityid = '2' and so on; or in()/find_in_set() )
到目前为止一切正常。我的问题是这有多高效?假设有100万用户,每个用户可以在city_relations表中拥有数百个城市。假设每个用户有100个城市,该表中将有100亿行运行插入/删除和选择 - 加入查询。
如果这种方式正常,我应该记住什么才能获得最佳性能?表上的索引就足够了? 如果这种方式可能会导致问题,您还建议采用其他方式吗?
您如何看待'不将所有关系存储在不同的行中并将它们保存在一个字段中'?
For example;
-----------
UserID
CityIDS (separated by commas)
答案 0 :(得分:0)
如果您可以将city
存储在另一行中,那就更好了。虽然像find_in_set()
这样的mysql中存在内置函数,但如果尝试其他数据库服务器则不够灵活。而且你说的是数十亿行而不是百万行。因此,查询的效率在这里是最重要的。
答案 1 :(得分:0)
重要的是在city_relations中索引两列。由于UserID,CityID可能是表的唯一主键,因此您不需要为UserID添加额外的索引(索引是B树,因此索引的列集的任何前缀也被索引),但是您将需要一个CityID索引。
我同意约翰的意见,你应该把城市分开。 find_in_set()无法利用索引,因此必须搜索每一行并执行复杂的字符串搜索。