Php 如何为在线交友网站设计用户表?
我正在开发本地在线交友网站的下一个版本,基于PHP和MySQL,我想把事情做好。用户表相当庞大,预计随着新版本的推出,会有更多的增长,因为会有很多钱花在推广上 目前的版本,我猜是7-8岁可能是由不太熟悉PHP和MySQL的人做的,所以我必须从头开始 该社区目前有20多万用户,预计在未来一到两年内将增长到50万到100万。每个用户的个人资料有100多个属性,我必须能够搜索其中至少30-40个 你可以想象,我对创建一个包含200k行和100列的表有点谨慎。我的前任将用户表一分为二。。。一个包含使用和搜索最多的列,另一个包含其余(和大部分)列。但这会导致两个表之间出现严重的同步问题Php 如何为在线交友网站设计用户表?,php,mysql,database-design,Php,Mysql,Database Design,我正在开发本地在线交友网站的下一个版本,基于PHP和MySQL,我想把事情做好。用户表相当庞大,预计随着新版本的推出,会有更多的增长,因为会有很多钱花在推广上 目前的版本,我猜是7-8岁可能是由不太熟悉PHP和MySQL的人做的,所以我必须从头开始 该社区目前有20多万用户,预计在未来一到两年内将增长到50万到100万。每个用户的个人资料有100多个属性,我必须能够搜索其中至少30-40个 你可以想象,我对创建一个包含200k行和100列的表有点谨慎。我的前任将用户表一分为二。。。一个包含使用和
那么,您认为最好的方法是什么呢?实体属性值模型可能非常适合您: 添加一个包含三列的表,而不是100列和不断增长的列:
用户标识
,属性
,值
如果不查看模式,就无法真正提出任何建议。一般来说,Mysql数据库必须规范化为至少3NF或BNCF。听起来好像它现在还没有标准化,一个表中有100列
此外,您可以使用事务和INNODB引擎轻松地使用外键强制执行引用完整性。您可以做的是跨两个表拆分用户数据帐户 1)表格:用户 这将包含关于用户的“核心”固定信息,如名字、姓氏、电子邮件、用户名、角色id、注册日期和类似性质的信息 配置文件相关信息可以放在它自己的表中。这将是一个具有key=>val性质的无限可扩展表 2)表格:用户配置文件 字段:用户id、选项、值 用户id:1 选项:配置文件\图像 值:/uploads/12/myimage.png 及 用户id:1 选项:回答的问题 数值:24 希望这有帮助,
Paul.一般来说,您不应该为了性能而牺牲数据库的完整性 我要做的第一件事是创建一个包含1百万行虚拟数据的表,并使用压力工具(如
ab
)测试一些典型的查询。结果很可能证明它的性能很好——对于mysql来说,一百万行是小菜一碟。所以,在试图解决一个问题之前,请确保你确实有它
如果发现性能不佳,数据库实际上是瓶颈,考虑一般优化,比如缓存(在所有级别上,从MySQL查询缓存到HTML缓存),得到更好的硬件等等。这在大多数情况下都应该解决。
< P>这本身不是答案,但由于这里很少有人提出属性-价值模型,我只想插话谈谈我的生活经历 我曾经尝试过将这个模型用于一个具有120多个属性的表(每年增长5-10个),并添加了大约100k+行(每6个月一次),索引增长如此之大,以至于需要永远添加或更新单个用户id
我发现这种设计的问题(并不是说它完全不适合任何情况)是需要在第二个表的user\u id,attrib
上放置主键。在不知道attrib的潜在长度的情况下,通常会使用更大的长度值,从而增加索引。在我的例子中,attribs可以有3到130个字符。而且,值
肯定也会受到相同假设的影响
正如OP所说,这会导致同步问题。想象一下,如果每个属性(或者至少50%的属性)都需要存在
此外,正如OP所建议的,搜索需要在30-40个属性上进行,我无法想象30-40个连接会有多高效,甚至由于长度限制,一个group\u concat()
我唯一可行的解决方案是返回到一个列数与属性数相同的表。我的索引现在大大缩小了,搜索也更容易了
编辑:而且,没有标准化问题。要么为属性值设置查找表,要么将它们设置为ENUM()
编辑2:当然,可以说我应该有一个查找表来查找属性可能的值(减少索引大小),但是我应该在该表上建立一个联接。通常,在担心性能之前,您应该始终正确地获取模式 这样,您就可以做出关于调整模式以解决特定性能问题的明智决策,而不是猜测 你绝对应该走2桌路线。这将大大减少存储量、代码复杂度,以及更改系统以添加新属性的工作量 假设每个属性都可以用一个表示,并且您只寻找对称匹配(即,您试图根据相似的属性而不是意图表达来匹配人) 在一个简单的层次上,查找合适匹配项的查询可能非常昂贵。实际上,您是在N维空间中寻找接近度相同的节点,不幸的是,大多数关系数据库并没有真正针对这种操作进行设置(我相信PostgreSQL支持这种操作)。因此,大多数人可能会从以下内容开始:
SELECT candidate.id,
COUNT(*)
FROM users candidate,
attributes candidate_attrs,
attributes current_user_attrs
WHERE current_user_attrs.user_id=$current_user
AND candidate.user_id<>$current_user
AND candidate.id=candidate_attrs.user_id
AND candidate_attrs.attr_type=current_user.attr_type
AND candidate_attrs.attr_value=current_user.attr_value
GROUP BY candidate.id
ORDER BY COUNT(*) DESC;
选择candidate.id,
计数(*)
从用户候选人,
属性候选属性,
属性当前用户属性
其中,当前用户\u属性.user\u id=$current\u user
和候选者。用户\u id$当前\u用户
和candidate.id=candidate\u attrs.user\u id
和候选者属性属性类型=当前
SELECT candidate.id,
COUNT(*)
FROM users candidate,
attributes candidate_attrs,
attributes current_user_attrs
WHERE current_user_attrs.user_id=$current_user
AND candidate.user_id<>$current_user
AND candidate.id=candidate_attrs.user_id
AND candidate_attrs.attr_type=current_user.attr_type
AND candidate_attrs.attr_value
BETWEEN current_user.attr_value+$tolerance
AND current_user.attr_value-$tolerance
GROUP BY candidate.id
ORDER BY COUNT(*) DESC;
SELECT candidate.id,
SUM(1/1+
((candidate_attrs.attr_value - current_user.attr_value)
*(candidate_attrs.attr_value - current_user.attr_value))
) as match_score
FROM users candidate,
attributes candidate_attrs,
attributes current_user_attrs
WHERE current_user_attrs.user_id=$current_user
AND candidate.user_id<>$current_user
AND candidate.id=candidate_attrs.user_id
AND candidate_attrs.attr_type=current_user.attr_type
AND candidate_attrs.attr_value
BETWEEN current_user.attr_value+$tolerance
AND current_user.attr_value-$tolerance
GROUP BY candidate.id
ORDER BY COUNT(*) DESC;
SELECT candidate.id,
SUM(1/1+
((candidate_attrs.attr_value - current_user.attr_value)
*(candidate_attrs.attr_value - current_user.attr_value))
) as match_score
FROM users candidate,
attributes candidate_attrs,
attributes current_user_attrs,
attribute_subsets s
WHERE current_user_attrs.user_id=$current_user
AND candidate.user_id<>$current_user
AND candidate.id=candidate_attrs.user_id
AND candidate_attrs.attr_type=current_user.attr_type
AND candidate_attrs.attr_value
AND s.subset_name=$required_subset
AND s.attr_type=current_user.attr_type
BETWEEN current_user.attr_value+$tolerance
AND current_user.attr_value-$tolerance
GROUP BY candidate.id
ORDER BY COUNT(*) DESC;