这两种方法中哪一种对PHP/MYSQL最有效


which of these 2 methods is most efficient with PHP/MYSQL

我有一些位置数据,这是在表locations中,键是唯一的location_id

我有一些用户数据,它在表users中,键是唯一的user_id

我想到了两种连接这两者的方法:

  1. 我可以把'location'放在每个用户的数据中。

    '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
    
  2. 我还可以将'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
    

所以我想知道,哪种方法最有效。我不太确定存储的数据大小对速度的影响有多大。当试图找出哪个用户在哪个位置时,我希望检索尽可能快。

这只是一个例子,还会有很多其他的表,比如位置表来和用户进行比较,所以效率,或者缺乏,将会在整个系统中成倍增加。

坚持选择1。在发现性能问题之前,尽可能保持数据库表的规范化。

选项2有很多问题,包括缺乏使用用户ID的能力,直到您将它们拉入PHP,然后必须为每个ID触发更多的SQL查询。这是非常低效的。尽可能在MySQL内部做,数据库层在运行查询时可以做的优化将比你用PHP写的任何东西都要快得多。

关于你关于不在主键上搜索的观点,你应该给location列添加一个索引。一般来说,WHERE子句中的所有列都应该被索引。这就消除了不在主键上搜索的问题,因为主键只是出于性能考虑的另一种类型的索引。

使用第一个来保持数据规范化。然后,您可以直接从数据库中查询某个位置的所有用户,而不必为每个用户返回数据库。

请确保在用户表中也添加了正确的索引。

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);

你听说过外键吗?

使用join获取多个表的详细信息。

也可以使用子查询。

如你所说,有两个表用户和位置。

当您将用户id作为逗号分隔的列表存储在表中时,该表不是规范化的(特别是它违反了第一种规范化形式,即第4项)。

为了优化目的而对表进行非规范化是完全有效的。但只有在你测量了这就是你的具体情况下的瓶颈所在之后。然而,只有当您知道哪个查询执行的频率、执行的时间以及查询的性能是否至关重要(相对于其他查询)时,才能确定这一点。

坚持使用选项1,除非你确切地知道为什么你必须反规范化你的表。