在阅读了来自
this great
Nettuts+ article
我已经提出了一个表模式,它可以将高度不稳定的数据从其他需要大量读取的表中分离出来,同时降低整个数据库模式中所需的表的数量,但是我不确定这是否是一个好主意,因为它不遵循规范化的规则。我想听听你的建议,总的来说是这样的:
我在一个
Class Table Inheritance
结构,在主“user”表中,我存储所有用户共有的数据(
id
,
username
,
password
几个
flags
,…)还有一些
TIMESTAMP
字段(
date_created
,
date_updated
,
date_activated
,
date_lastLogin
,……)
引用上述nettuts+文章中的提示16:
例2
:您有一个“最后登录名”
在你的桌子上。它每
用户登录网站的时间。
但是表上的每个更新都会导致
查询该表的缓存
脸红的你可以把那块地
另一个表来更新您的
用户表最小化。
现在它变得更加棘手了,我需要跟踪一些用户统计数据,比如
-
有多少
独特的
查看用户配置文件的次数
-
有多少
独特的
时代A
从一个广告
特定类型的用户
被点击
-
有多少
独特的
时代A
从一个帖子
特定类型的用户
被看见
-
等等…
在我的完全规范化的数据库中,这加起来大约有8到10个额外的表,虽然不多,但如果可能的话,我希望保持简单,所以我提出了以下建议”
events
表:
|------|----------------|----------------|---------------------|-----------|
| ID | TABLE | EVENT | DATE | IP |
|------|----------------|----------------|---------------------|-----------|
| 1 | user | login | 2010-04-19 00:30:00 | 127.0.0.1 |
|------|----------------|----------------|---------------------|-----------|
| 1 | user | login | 2010-04-19 02:30:00 | 127.0.0.1 |
|------|----------------|----------------|---------------------|-----------|
| 2 | user | created | 2010-04-19 00:31:00 | 127.0.0.2 |
|------|----------------|----------------|---------------------|-----------|
| 2 | user | activated | 2010-04-19 02:34:00 | 127.0.0.2 |
|------|----------------|----------------|---------------------|-----------|
| 2 | user | approved | 2010-04-19 09:30:00 | 217.0.0.1 |
|------|----------------|----------------|---------------------|-----------|
| 2 | user | login | 2010-04-19 12:00:00 | 127.0.0.2 |
|------|----------------|----------------|---------------------|-----------|
| 15 | user_ads | created | 2010-04-19 12:30:00 | 127.0.0.1 |
|------|----------------|----------------|---------------------|-----------|
| 15 | user_ads | impressed | 2010-04-19 12:31:00 | 127.0.0.2 |
|------|----------------|----------------|---------------------|-----------|
| 15 | user_ads | clicked | 2010-04-19 12:31:01 | 127.0.0.2 |
|------|----------------|----------------|---------------------|-----------|
| 15 | user_ads | clicked | 2010-04-19 12:31:02 | 127.0.0.2 |
|------|----------------|----------------|---------------------|-----------|
| 15 | user_ads | clicked | 2010-04-19 12:31:03 | 127.0.0.2 |
|------|----------------|----------------|---------------------|-----------|
| 15 | user_ads | clicked | 2010-04-19 12:31:04 | 127.0.0.2 |
|------|----------------|----------------|---------------------|-----------|
| 15 | user_ads | clicked | 2010-04-19 12:31:05 | 127.0.0.2 |
|------|----------------|----------------|---------------------|-----------|
| 2 | user | blocked | 2010-04-20 03:19:00 | 217.0.0.1 |
|------|----------------|----------------|---------------------|-----------|
| 2 | user | deleted | 2010-04-20 03:20:00 | 217.0.0.1 |
|------|----------------|----------------|---------------------|-----------|
基本上
ID
指主键(
身份证件
)领域
TABLE
桌子,我相信其他的应该很简单。在这个设计中,我喜欢的一件事是,我可以跟踪所有用户登录,而不仅仅是最后一次登录,从而用这些数据生成一些有趣的度量。
由于
事件
表我还考虑了一些优化,例如:
-
α9
:由于只有有限数量的表和有限(和预定)数量的事件,
桌子
和
EVENTS
列可以设置为
ENUM
S而不是
VARCHAR
为了节省一些空间。
-
α14
商店
IP
S AS
UNSIGNED INT
S
具有
INET_ATON()
而不是
瓦卡尔
S.
-
商场
DATE
S AS
时间戳
S
而不是
DATETIME
S.
-
使用
ARCHIVE
(
或
CSV
?
)发动机而不是
InnoDB
/
MyISAM
.
-
只有
INSERT
S和
SELECT
支持,并动态压缩数据。
总的来说,每个事件只需要14个字节(未压缩),这对我的流量来说是可以的。
赞成的意见:
-
能够存储更详细的数据(如登录)。
-
不需要设计(
代码
)几乎有十几个附加表(日期和统计数据)。
-
每个表减少几列,并保持易失性数据的分离。
欺骗:
-
非关系型(仍然没有eav差):
-
SELECT * FROM events WHERE id = 2 AND table = 'user' ORDER BY date DESC();
-
每个事件6字节的开销(
身份证件
,
表
和
EVENT
)
我更倾向于采用这种方法,因为利大于弊,但我还是有点不情愿…
我遗漏了什么吗?你对此有什么看法?
谢谢!
@酷客:
有件事我会做
不同的是保持
实体类型表,并在
对象类型列(在您的情况下,
“表”列)。你会想
对事件类型执行相同的操作
表。
为了清楚起见,您的意思是我应该添加一个额外的表来映射表中允许的事件,并在事件表中使用该表的pk,而不是使用
桌子
/
事件
一对?
本:
这些都是从
现有的数据,不是吗?
附加表主要与统计数据有关,但数据不存在,例如:
user_ad_stats user_post_stats
------------- ---------------
user_ad_id (FK) user_post_id (FK)
ip ip
date date
type (impressed, clicked)
如果我删除这些表,我就无法跟踪谁、什么或什么时候,不知道视图在这里有什么帮助。
我同意应该分开,
但更重要的是
不同的数据。什么样的人
有人做的是两件不同的事
东西。我不认为波动性是如此
重要的。
我听过这两种说法,但在mysql手册中找不到任何一种说法是正确的。无论如何,我同意您的看法,它们应该是分开的表,因为它们表示各种类型的数据(另外一个好处是比常规方法更具描述性)。
我想你错过了森林
可以说是树木。
表的谓词是
“时间日期IP中的用户ID
“似乎”
合理,但也有问题。
我的意思是“不比eav差”是所有记录都遵循线性结构,而且它们很容易查询,没有层次结构,所以所有查询都可以用一个简单的
选择
.
关于你的第二个陈述,我认为你在这里理解错了;IP地址不一定与用户相关。表结构应该如下所示:
IP地址(IP地址)
知识产权
)做了些什么
(
事件
)去PK(
身份证件
的
表(表)
桌子
)日期
日期
)
例如,在我上面的示例的最后一行中,它应该读取IP 217.0.0.1(某些管理员),在2010-04-20 03:20:00删除用户2(其最后已知IP为127.0.0.2)。
你仍然可以加入,比如说,用户事件
对于用户,但不能实现
外键约束。
的确,这是我最关心的问题。但是我不完全确定这个设计会出什么问题,而传统的关系设计不会出什么问题。我可以找出一些注意事项,但只要搞乱数据库的应用程序知道它在做什么,我想应该不会有任何问题。
在这个论点中,另一件重要的事情是,我将存储更多的事件,并且每个事件将比原始设计多出一倍,使用
档案文件
这里的存储引擎,唯一的问题是它不支持
FK
(既不)
UPDATE
S或
DELETE
s)。