Cassandra 非规范化与规范化
Cassandra denormalization vs normalization
非规范化现实
在我的数据库中,我有以下非规范化 table,它非常适合我的用例,而且我接收数据的速度非常快...
CREATE TABLE IF NOT EXISTS lp_webmap.link (
drank int,
prank int,
title text,
nofollow boolean,
created timestamp,
updated timestamp,
dst_ssl boolean,
dst_www boolean,
src_ssl boolean,
src_www boolean,
dst_domain_name1st text,
dst_domain_name2nd text,
dst_domain_name3rd text,
src_domain_name1st text,
src_domain_name2nd text,
src_domain_name3rd text,
dst_page text,
src_page text,
dst_page_title text,
src_page_title text,
src_domain_ownerreg text,
PRIMARY KEY (
(
dst_domain_name1st,
dst_domain_name2nd,
dst_domain_name3rd
),
created,
dst_page,
src_page,
src_domain_name1st,
src_domain_name2nd,
src_domain_name3rd
)
);
但是,此 table 中有数十亿行,这对我们的硬件来说是一个问题。因此,link table 设计中的每个备用字节对我们都有很大的好处。
归一化解?
应用程序中 link table 的平均值 select 包含十分之一/数百行。在最坏的情况下,selects 包含数千行。所以使用这个 table...
来标准化问题可能是(恕我直言)明智的
CREATE TABLE IF NOT EXISTS lp_webmap.page (
domain_name1st text,
domain_name2nd text,
domain_name3rd text,
location text,
title text,
rank int,
www boolean,
update_interval smallint,
updated timestamp,
PRIMARY KEY (
(domain_name1st, domain_name2nd, domain_name3rd, location),
updated, rank, update_interval
)
);
问题
如果我使用规范化 link 和页面 table,我需要将它们加入应用程序。那不会有问题,但是如何从页面 table 有效地 select 对应行呢?我感觉到逐个遍历 link table 和 select 相应页面行的每个结果行是无效的。
确实,JOIN 效率不高,尤其是其中一个 table 非常大。一个可能的解决方案是建立一个额外的物化视图,或者某种索引来快速搜索特定的列。这将使存储量翻倍,但无法同时实现:减少 space 消耗并提高 JOIN 查询性能。
也许您需要一个额外的硬盘驱动程序来支持新的视图或索引。
必须注意的一点是,当我们建立额外的视图或索引时,更新某些列会花费额外的时间(资源)。比如我们有两个table:订单和用户,我们通过JOIN搜索用户"jack"的所有订单。它是一个规范化版本。在实体化视图中,用户 "jack",他的所有列都合并到他的订单中以便快速访问:
primary_key, order_id, order_product, order_payment, user_name, user_age, user_favorite_color
1, 1, iphone, 1000, jack, 25, blue,
2, 3, book, 30, jack, 25, blue,
3, 6, car, 10000, jack, 25, blue,
其中 user_age、user_favorite_color 是从用户 table 中提取的冗余信息。当杰克改变他最喜欢的颜色时,所有这些记录都必须改变它们对应的列。通常一个数据库系统会启动一个后端线程来完成这个更新工作,但它仍然是一个耗时的过程,imaging jack 有数千个订单。
非规范化现实
在我的数据库中,我有以下非规范化 table,它非常适合我的用例,而且我接收数据的速度非常快...
CREATE TABLE IF NOT EXISTS lp_webmap.link (
drank int,
prank int,
title text,
nofollow boolean,
created timestamp,
updated timestamp,
dst_ssl boolean,
dst_www boolean,
src_ssl boolean,
src_www boolean,
dst_domain_name1st text,
dst_domain_name2nd text,
dst_domain_name3rd text,
src_domain_name1st text,
src_domain_name2nd text,
src_domain_name3rd text,
dst_page text,
src_page text,
dst_page_title text,
src_page_title text,
src_domain_ownerreg text,
PRIMARY KEY (
(
dst_domain_name1st,
dst_domain_name2nd,
dst_domain_name3rd
),
created,
dst_page,
src_page,
src_domain_name1st,
src_domain_name2nd,
src_domain_name3rd
)
);
但是,此 table 中有数十亿行,这对我们的硬件来说是一个问题。因此,link table 设计中的每个备用字节对我们都有很大的好处。
归一化解?
应用程序中 link table 的平均值 select 包含十分之一/数百行。在最坏的情况下,selects 包含数千行。所以使用这个 table...
来标准化问题可能是(恕我直言)明智的CREATE TABLE IF NOT EXISTS lp_webmap.page (
domain_name1st text,
domain_name2nd text,
domain_name3rd text,
location text,
title text,
rank int,
www boolean,
update_interval smallint,
updated timestamp,
PRIMARY KEY (
(domain_name1st, domain_name2nd, domain_name3rd, location),
updated, rank, update_interval
)
);
问题
如果我使用规范化 link 和页面 table,我需要将它们加入应用程序。那不会有问题,但是如何从页面 table 有效地 select 对应行呢?我感觉到逐个遍历 link table 和 select 相应页面行的每个结果行是无效的。
确实,JOIN 效率不高,尤其是其中一个 table 非常大。一个可能的解决方案是建立一个额外的物化视图,或者某种索引来快速搜索特定的列。这将使存储量翻倍,但无法同时实现:减少 space 消耗并提高 JOIN 查询性能。
也许您需要一个额外的硬盘驱动程序来支持新的视图或索引。
必须注意的一点是,当我们建立额外的视图或索引时,更新某些列会花费额外的时间(资源)。比如我们有两个table:订单和用户,我们通过JOIN搜索用户"jack"的所有订单。它是一个规范化版本。在实体化视图中,用户 "jack",他的所有列都合并到他的订单中以便快速访问:
primary_key, order_id, order_product, order_payment, user_name, user_age, user_favorite_color
1, 1, iphone, 1000, jack, 25, blue,
2, 3, book, 30, jack, 25, blue,
3, 6, car, 10000, jack, 25, blue,
其中 user_age、user_favorite_color 是从用户 table 中提取的冗余信息。当杰克改变他最喜欢的颜色时,所有这些记录都必须改变它们对应的列。通常一个数据库系统会启动一个后端线程来完成这个更新工作,但它仍然是一个耗时的过程,imaging jack 有数千个订单。