MYSQL SET数据类型的替代方案

时间:2014-07-08 03:11:53

标签: php mysql

我有一个列,我想存储用户的订阅(即他们在我的订阅平台上订阅了什么)我尝试使用SET数据类型,但它有64个值的限制,用户可以订阅的数量可能超过64个如果用户订阅超过64项,则会出现问题。

我还尝试了另一个表,在订阅时将user_id映射到item_id,但是当数据库开始增长时,这可能是一个缺点。

任何有更好主意的人?

1 个答案:

答案 0 :(得分:4)

重复属性的规范方法是第二个表。

为什么你认为当数据库开始增长时,单独的表将成为一个缺点,这一点并不清楚。


<强>后续

问:如果我有第二个表,其中包含最多10,000个用户订阅值,并且我正在寻找用户的唯一一个订阅,那么查询将需要更长时间。我正在考虑将用户的订阅存储为用户表中的对象,如字符串对象,我只是查询

答:不,如果第二个表具有合适的索引,则第二个表的查询不会花费更长的时间。

查询实际上会更快

<强> -- sample table

CREATE TABLE user_subscription 
( user_id         INT(10) UNSIGNED NOT NULL COMMENT 'PK, FK to user.id'
, subscription_id INT(10) UNSIGNED NOT NULL COMMENT 'PK'
, PRIMARY KEY (user_id,subscription_id)
, UNIQUE KEY user_subscription_UX1 (subscription_id,user_id)
) ENGINE=INNODB ;

<强> -- populate

INSERT INTO user_subscription
SELECT s.d*10000 + u.d*1000 + h.d*100 + t.d*10 + o.d + 1 AS user_id, 1
  FROM digit s
  JOIN digit u
  JOIN digit h
  JOIN digit t
  JOIN digit o
 ORDER BY s.d, u.d, h.d, t.d, o.d ;
INSERT INTO user_subscription
SELECT s.user_id, s.subscription_id + 1
  FROM user_subscription s
 WHERE s.subscription_id = 1 ;      
INSERT INTO user_subscription
SELECT s.user_id, s.subscription_id + 2
  FROM user_subscription s
 WHERE s.subscription_id <= 2 ;      
INSERT INTO user_subscription
SELECT s.user_id, s.subscription_id + 4
  FROM user_subscription s
 WHERE s.subscription_id <= 4 ;      

<强> -- total rows

SELECT COUNT(1) FROM user_subscription
COUNT(1)  
----------
    800000

<强> -- sample query 1

EXPLAIN
SELECT t.*
  FROM user_subscription t
 WHERE t.user_id = 878

id select_type table  type   possible_keys key     key_len ref      rows Extra        
-- ----------- ------ ------ ------------- ------- ------- -----  ------ -----------
 1 SIMPLE      t      ref    PRIMARY       PRIMARY 4       const       8 Using index  

- 示例查询2

EXPLAIN
SELECT t.*
  FROM user_subscription t
 WHERE t.subscription_id = 4

id select_type table  type possible_keys         key                   key_len ref      rows Extra
-- ----------- ------ ---- --------------------- --------------------- ------- -----  ------  -------------
1 SIMPLE       t      ref  user_subscription_UX1 user_subscription_UX1 4       const  184412  Using index

将此与将用户的“预订”存储为VARCHAR列中的列表进行比较(与SET数据类型中使用的数据库相同或相同的表示形式。并编写查询识别具有特定订阅的用户,例如

EXPLAIN
SELECT u.user_id
  FROM users u
 WHERE FIND_IN_SET(4,u.subscriptions)

您会发现MySQL需要检查users表中的每个行,看看是否符合条件。