关于php:在RDMS中是否存在以逗号分隔的字符串存储id的性能原因?

Is there any performance reason to store ids as comma seperated string in a RDMS?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Is storing a delimited list in a database column really that bad?

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

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

(在伪代码中)

1
2
3
4
5
6
7
8
9
table people
id - integer
name - string
age - integer
teams - string (CSV OF integers, ex '1,3,9,21')

table teams
name - String
id - integer

管理关系变得很麻烦。

让一个人获得所有团队:

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

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

1
$person['teams'] = SELECT * FROM teams WHERE id IN ($person['teams']);

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

1
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

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

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

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


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

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

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

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

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


表扫描在任何时候都不能被视为一种好处。

此外,就我记得从学校来说,它打破了普通形式(http://en.wikipedia.org/wiki/Database_normalization)。

我认为将所有主键/外键列编入索引以获得性能优势是一种很好的做法。

在这种情况下,我唯一的想法是礼貌地询问建筑师在特定项目上他的解决方案背后的想法,并解释他/她背后的性能灾难:)