Php MYSQL集数据类型的替代方案

Php MYSQL集数据类型的替代方案,php,mysql,Php,Mysql,我有一个列,我想在其中存储用户的订阅(即他们在我的订阅平台上订阅的内容),我尝试使用SET-datatype,但它有64个值的限制,用户可以订阅的内容可能超过64个,如果用户订阅超过64个项目,则会出现问题 我还尝试使用另一个表在订阅时将用户id映射到项目id,但当数据库开始增长时,这可能是一个缺点 谁有更好的想法?重复属性的标准方法是第二个表 现在还不清楚为什么您认为“当数据库开始增长时”,单独的表会成为一个缺点 跟进 Q:如果我有第二个表,其中包含多达10000个用户订阅值,并且我只查找用

我有一个列,我想在其中存储用户的订阅(即他们在我的订阅平台上订阅的内容),我尝试使用SET-datatype,但它有64个值的限制,用户可以订阅的内容可能超过64个,如果用户订阅超过64个项目,则会出现问题

我还尝试使用另一个表在订阅时将用户id映射到项目id,但当数据库开始增长时,这可能是一个缺点


谁有更好的想法?

重复属性的标准方法是第二个表

现在还不清楚为什么您认为“当数据库开始增长时”,单独的表会成为一个缺点


跟进


Q:如果我有第二个表,其中包含多达10000个用户订阅值,并且我只查找用户的一个订阅,那么查询将花费更长的时间。我正在考虑将用户的订阅作为一个对象存储在users表中,就像我将要查询的string对象一样

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

查询实际上会更快

--示例表

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 ;
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 ;      
SELECT COUNT(1) FROM user_subscription
COUNT(1)  
----------
    800000
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  
--填充

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 ;
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 ;      
SELECT COUNT(1) FROM user_subscription
COUNT(1)  
----------
    800000
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  
--示例查询1

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 ;
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 ;      
SELECT COUNT(1) FROM user_subscription
COUNT(1)  
----------
    800000
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
表中的每一行,以查看是否满足标准。

重复属性的标准方法是第二个表

现在还不清楚为什么您认为“当数据库开始增长时”,单独的表会成为一个缺点


跟进


Q:如果我有第二个表,其中包含多达10000个用户订阅值,并且我只查找用户的一个订阅,那么查询将花费更长的时间。我正在考虑将用户订阅作为一个对象存储在用户表中,就像我只查询的字符串对象一样

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

查询实际上会更快

--示例表

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 ;
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 ;      
SELECT COUNT(1) FROM user_subscription
COUNT(1)  
----------
    800000
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  
--填充

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 ;
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 ;      
SELECT COUNT(1) FROM user_subscription
COUNT(1)  
----------
    800000
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  
--示例查询1

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 ;
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 ;      
SELECT COUNT(1) FROM user_subscription
COUNT(1)  
----------
    800000
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
表中的每一行,以查看是否符合标准。

SET的缺点是您必须发出ALTER语句来获取另一个SET值。因为它不是适合预期用途的解决方案。第二个表是适合的,没有@spencer的缺点SET的缺点是您必须发出ALTER语句才能获得另一个SET值。因为SET不是适合预期用途的解决方案。第二个表是一个合适的表,没有@spencer7593所说的任何缺点。如果我有第二个表,其中包含多达10000个用户订阅值,我正在寻找一个用途r只有一个订阅,查询需要更长的时间。我正在考虑将用户的订阅作为一个对象存储在users表中,就像一个字符串对象一样,我只是从中查询,但不知道如何工作out@Tobby:可能需要“更长的查询时间”当然,表上没有定义合适的索引;有了合适的索引,让用户订阅某些内容将非常快;如果这些内容作为VARCHAR的一部分存储在每个用户行中,则数据库将被迫查看表中的每个翻转行,查看每个用户,以确定该用户是否为子用户另外,向用户添加订阅和从所有用户中删除特定订阅等操作将需要更多的资源。如果我有第二个表,其中包含多达10000个用户订阅值,并且我只查找用户的一个订阅,则需要更长的时间来查询。我认为f将用户的订阅作为一个对象存储在users表中,就像一个字符串对象,我只是从中查询,但不知道如何工作out@Tobby:可能需要“更长的查询时间”当然,表上没有定义合适的索引;有了合适的索引,让用户订阅某些内容将非常快;如果这些内容作为VARCHAR的一部分存储在每个用户行中,则数据库将被迫查看表中的每个翻转行,查看每个用户,以确定该用户是否为子用户此外,向用户添加订阅以及从所有用户中删除特定订阅等操作将需要更多资源。