是否有任何性能原因将RD存储为RDMS中的逗号分隔字符串?

dm0*_*514 1 php mysql database-design

可能重复:
在数据库列中存储分隔列表真的那么糟糕吗?

我一直致力于几个PHP/MySQL项目,其中所有关系都以逗号分隔的字符串存储.

例如,一种常见的关系就像

(在伪代码中)

table people
id - integer
name - string
age - integer
teams - string (CSV OF integers, ex '1,3,9,21')

table teams
name - String
id - integer
Run Code Online (Sandbox Code Playgroud)

管理关系变得很麻烦.

让一个人获得所有团队:

$person = 'SELECT * FROM People WHERE id= x';

然后在PHP我一直在做类似的事情

$person['teams'] = SELECT * FROM teams WHERE id IN ($person['teams']);
Run Code Online (Sandbox Code Playgroud)

当我写这篇文章时,我意识到我可能会将它们组合在一个mysql查询中,例如:

select people.id, people.name, people.teams, teams.name from people JOIN teams ON FIND_IN_SET(teams.id, people.teams) where people.id=x
Run Code Online (Sandbox Code Playgroud)

通过这种类型的设置,我发现自己FIND_IN_SET经常使用

最后,我的问题是:创建这样的关系是否有性能优势?

根据我迄今为止的经验,FIND_IN_SET通常都在进行全表扫描.如果没有性能优势,在哪些情况下使用逗号分隔的整数列表是否有益? 在创建FIND_IN_SET时,似乎mysql设计者已经想到了一些东西.

Bil*_*win 6

你是对的,FIND_IN_SET()不能使用索引,因此它会导致全表扫描.从技术上讲,该函数对于关系数据库来说是一种虚假的操作,但毫无疑问对它有很多需求,因此MySQL实现了它.

将数据存储在以逗号分隔的列表中是非规范化的示例.任何偏离规范化设计都可以为一种类型的查询提供性能提升,但通常以牺牲针对相同数据的所有其他类型的查询为代价.

例如,如果您将玩家及其团队存储为以逗号分隔的列表,则可以非常轻松地获取给定玩家的团队列表,而无需进行连接.这是性能提升.但是获取给定玩家团队的详细信息要困难得多.同样搜索特定团队中的所有玩家.

仅当该列表被视为离散的"黑匣子"数据时,才使用逗号分隔列表.即您的应用程序需要将该列表作为整个项目获取,但从不是列表的子集,并且您永远不需要编写SQL来使用该列表中的元素进行搜索,加入,排序,小计等.

另请参阅我的答案是否将分隔列表存储在数据库列中真的那么糟糕?