使用PHP / MYSQL,这两种方法中哪一种最有效

时间:2011-05-02 01:12:35

标签: php mysql performance

我有一些位置数据,位于表locations中,密钥为唯一location_id

我有一些用户数据,位于表users中,密钥为唯一user_id

我想把这两者联系在一起的两种方式:

  1. 我可以在每个用户的数据中加上“位置”。

    '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
    
  3. 所以我想知道,这将是最有效的。我不确定存储的数据大小会对速度产生多大影响。我想在尝试找出哪些用户位于哪个位置时尽可能快地进行检索。

    这只是一个例子,并且会有许多其他表格,比如位置与用户进行比较,因此效率或缺乏将在整个系统中成倍增加。

4 个答案:

答案 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,除非您确切知道为什么必须对表进行非规范化。