我有一些位置数据,位于表locations
中,密钥为唯一location_id
我有一些用户数据,位于表users
中,密钥为唯一user_id
我想把这两者联系在一起的两种方式:
我可以在每个用户的数据中加上“位置”。
'SELECT user_id FROM users WHERE location = "LOCATIONID";'
//this IS NOT searching with the table's key
//this does not require an explode
//this stores 1 integer per user
我还可以将'userIDs'作为逗号分隔的id字符串放入每个位置的数据中。
'SELECT userIDs FROM locations WHERE location_id = "LOCATIONID";'
//this IS searching with the tables key
//this needs an explode() once the comma delimited list is retrieved
//this stores 1 string of user ids per location
所以我想知道,这将是最有效的。我不确定存储的数据大小会对速度产生多大影响。我想在尝试找出哪些用户位于哪个位置时尽可能快地进行检索。
这只是一个例子,并且会有许多其他表格,比如位置与用户进行比较,因此效率或缺乏将在整个系统中成倍增加。
答案 0 :(得分:4)
坚持使用选项1.尽可能保留数据库表normalised,直到您知道性能问题为止。
选项2存在很多问题,包括缺乏使用用户ID的能力,直到你将它们拉入PHP然后不得不为每个ID启动更多的SQL查询。 效率非常低。尽可能多地在MySQL内部进行,数据库层在运行查询时可以进行的优化比使用PHP编写的任何内容都快得多。
关于您没有搜索主键的观点,您应该add an index到位置列。 WHERE
子句中的所有列都应作为一般规则编制索引。这消除了不搜索主键的问题,因为主键只是用于性能目的的另一种类型的索引。
答案 1 :(得分:0)
使用第一个来保持数据规范化。然后,您可以直接从数据库查询位置的所有用户,而无需返回每个用户的数据库。
请务必在您的用户表格中添加正确的索引。
CREATE TABLE locations (
locationId INT PRIMARY KEY AUTO_INCREMENT
) ENGINE=INNODB;
CREATE TABLE users (
userId INT PRIMARY KEY AUTO_INCREMENT,
location INT,
INDEX ix_location (location)
) ENGINE=INNODB;
或者只添加索引
ALTER TABLE users ADD INDEX ix_location(location);
答案 2 :(得分:0)
您听说过外键吗?
使用加入从许多表格表中获取详细信息。
您也可以使用子查询。
正如您所说,有两个表用户和位置。
将userid作为外键保存在位置中并根据它获取。
答案 3 :(得分:0)
当您将用户ID存储为表中以逗号分隔的列表时,该表未进行规范化(特别是它违反了first normal form,第4项)。
为了优化目的,对表进行非规范化是完全有效的。但只有在你测量到这是瓶颈实际上在你的特定情况下。但是,如果您知道执行的查询频率,执行时间以及查询的性能是否至关重要(与其他查询相关),则只能确定这一点。
坚持选项1,除非您确切知道为什么必须对表进行非规范化。