`
lvsenlin
  • 浏览: 125638 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

MySQL key/value 表的两种设计

 
阅读更多

Friendfeed的MySQL key/value存储

这是一篇2009年初的资料How FriendFeed uses MySQL to store schema-less data,相信大部分人已经看过了。如Fenng的中文介绍FriendFeed 使用 MySQL 的经验。本文从不同的角度再补充下。作者几个月前也曾经在广州技术沙龙作过一次Key value store漫谈的演讲,许多参会人员对key value方向存在强烈的使用意愿,但同时也对完全抛弃MySQL存在疑虑,本文介绍的方案也可以给这些人员一些架构参考。
需求250M entities, entities表共有2.5亿条记录,当然是分库的。
典型解决方案:RDBMS问题:由于业务需要不定期更改表结构,但是在2.5亿记录的表上增删字段、修改索引需要锁表,最长需要1小时到1天以上。
Key value方案评估Document类型数据库,如CouchDB
CouchDB问题: Performance? 广泛使用? 稳定性? 抗压性?
MySQL方案MySQL相比Document store优点:

  • 不用担心丢数据或数据损坏
  • Replication
  • 非常熟悉它的特性及不足,知道如何解决
结论综合取舍,使用MySQL来存储key/value(schema-less)数据,value中可以放:# |7 u. ~& s: q! y. C0 T% I( m
Python dict+ N5 W# e/ |+ w; i
JSON object- B$ l. K5 b! `2 O" `0 o: D6 |- |
实际friendfeed存放的是zlib压缩的Python dict数据,当然这种绑定一种语言的做法具有争议性。5 l4 W* s: h" |* [- \
表结构及Index设计模式feed数据基本上都存在entities表中,它的结构为
mysql> desc entities;8 t0 e7 Q1 w$ T2 F5 f
+----------+------------+------+-----+-------------------+----------------+4 H" @7 V( o0 D
| Field    | Type       | Null | Key | Default           | Extra          |
+----------+------------+------+-----+-------------------+----------------+- N- K  H4 ~. R, B+ y
| added_id | int(11)    | NO   | PRI | NULL              | auto_increment |7 \! o7 C) X( R+ B" V% ]3 w
| id       | binary(16) | NO   | UNI |                   |                |  w" n8 s6 F2 j+ {' `* ?
| updated  | timestamp  | YES  | MUL | CURRENT_TIMESTAMP |                |
| body     | mediumblob | YES  |     | NULL              |                |
+----------+------------+------+-----+-------------------+----------------+假如里面存的数据如下  ^8 y% n" n2 U, `9 P" U$ P
{! x8 B6 e. w/ {0 o/ {
"id": "71f0c4d2291844cca2df6f486e96e37c",( a* A% T. w+ H: y
"user_id": "f48b0440ca0c4f66991c4d5f6a078eaf",  e  s- [. a: n0 n7 S1 g1 o
"feed_id": "f48b0440ca0c4f66991c4d5f6a078eaf",# }$ G8 A- ^0 O# _4 E4 X
"title": "We just launched a new backend system for FriendFeed!",
"link": "http://friendfeed.com/e/71f0c4d2-2918-44cc-a2df-6f486e96e37c",
"published": 1235697046,+ d+ {2 ~3 P8 j: t  X' b
"updated": 1235697046,/ c0 L" c( f- w& W: L
}如果要对link字段进行索引,则用另外一个表来存储。
mysql> desc index_link;7 H9 H& ^( c" x% q" m" R3 f
+-----------+--------------+------+-----+---------+-------+6 w5 B  a# }2 H+ H( h5 ~
| Field     | Type         | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+1 Z2 m/ y2 l& O; `
| link      | varchar(255) | NO   | PRI |         |       |
| entity_id | binary(16)   | NO   | PRI |         |       |, J, M2 j( a& J
+-----------+--------------+------+-----+---------+-------+" k4 q+ b9 y+ Y0 Z
2 rows in set (0.00 sec)优点是
  • 增加索引时候只需要 1. CREATE TABLE,2.更新程序
  • 删除索引时候只需要 1. 程序停止写索引表(实际就是一个普通表),2. DROP TABLE 索引表

这种索引方式也是一种值得借鉴的设计模式,特别是key value类型的数据需要索引其中的内容时。

 

 

Mysql 表设式模式之 Key Value Table

 

Key/value approach in database design could come in handy when we need to store some arbitrary data about another table.

Key/Value 模式用于储存关于另外一张表的任意相关数据。算了,还是不翻了,丢人。

举例:
有一张users表,很简单的,就保存了用户名和密码,然后有一个自增字段。

 
CREATE TABLE IF NOT EXISTS `users` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `username` VARCHAR(255) COLLATE utf8_unicode_ci NOT NULL,
  `pass` VARCHAR(255) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM ;

上线运行之后,挺好用的。
不过,有一天,客户决定还要保存用户的电话号码,年龄,性别,住址等信息。

通常的作法是在users表上扩展字段

ALTER TABLE `users` ADD `phone` CHAR(32);
ALTER TABLE `users` ADD `mobile` CHAR(32);
......
......

或者是创建另外一张user_details表,然后通过user_id字段和users表关联:

CREATE TABLE user_details (
`id` INT AUTO_INCREMENT,
`user_id` INT,
`phone` CHAR(32),
`mobile` CHAR(32),
......
PRIMARY KEY(`id`)
) ;

这样做的问题在于,如果要添加的字段相当的多,表会横向增长到难以忍受的地步。

来看一下如何使用Key/Value模式的表:

 
CREATE TABLE IF NOT EXISTS `user_details` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `user_id` INT(11) NOT NULL,
  `key` VARCHAR(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `value` VARCHAR(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM;

仍然是通过user_id字段与users主表关联。
key 和 value字段,会保存用户的资料: 比如key为”城市”, value为”北京市”,
或者key为’生日’, value为’1982-02-10′;

优点:
在这样的结构下,数据只会纵向增长,我们可以保存任意多的用户资料。
这种模式使得最开始的数据库设计非常简单,(users表只有3个字段)
后面再想添加/删除用户属性,也变得很简单。

下面再考虑一下这种模式的缺点。

缺点一:
mysql的字段有一个天然的优势:它限制了字段中数据的类型。比如int char等。
Key/Value模式下,字段类型丢失。
比如下面这条sql语句:

UPDATE user_data SET VALUE = '111111111' WHERE KEY = '生日'

本来应该是date类型的字段,却保存了一个莫名其妙的字符串。

话说在php层面,检测一下数据的类型,就可以克服这个缺点了。

缺点二:
假如我们只有一张users表,所有字段都在一起,
要查找所在城市为’北京市’的用户,只要极其简单的sql语句就可以:

SELECT username FROM users WHERE city = '北京市'

在Key/Value模式中,就要用到JOIN操作了:

 
SELECT username FROM users a
INNER JOIN user_data b
    ON a.id = b.user_id
WHERE b.KEY = '城市'
AND b.VALUE = '北京市'

或许你觉得这也不算什么大问题。

如果要同时在二个或多个字段上过滤。。。就要死人了:

SELECT username FROM users WHERE city = '北京市' AND DATE= '1980-10-10'

不得不JOIN二次。。

SELECT username FROM users a
INNER JOIN user_data b
ON a.id = b.user_id
    INNER JOIN user_data c
    ON b.user_id = c.user_id
WHERE
    (b.KEY = '城市' AND b.VALUE = '北京市')
AND
    (c.KEY = '生日' AND c.VALUE = '1980-10-10')

试图JOIN一次的作法是错误的:

 
SELECT username FROM users a
    INNER JOIN user_data b
    ON a.id = b.user_id
WHERE
    (b.KEY = '城市' AND b.VALUE = '北京市')
AND
    (b.KEY = '生日' AND b.VALUE = '1980-10-10')

因为在user_data b表中,肯定没有一行同时满足
(b.key = ‘城市’ AND b.value = ‘北京市’)和(b.key = ‘生日’ AND b.value = ’1980-10-10′)。

好了,最后再总结一下:
Key/Value的表设计模式虽然灵活,但是最好不要在上面做多个字段的过滤。

分享到:
评论

相关推荐

    C 语言实现 linux pwd 命令内含源码以及说明书可以自己运行复现.zip

    C 语言实现 linux pwd 命令内含源码以及说明书可以自己运行复现.zip

    2024年中国变焦LED手电筒行业研究报告.docx

    2024年中国变焦LED手电筒行业研究报告

    node-v8.11.2-darwin-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    node-v4.8.2-x86.msi

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    ffmpeg 结合 SDL 编写播放器内含源码以及说明书可以自己运行复现.zip

    ffmpeg 结合 SDL 编写播放器内含源码以及说明书可以自己运行复现.zip

    2024-2030中国OPzV胶体电池市场现状研究分析与发展前景预测报告.docx

    2024-2030中国OPzV胶体电池市场现状研究分析与发展前景预测报告

    node-v4.9.0-win-x64.zip

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    2024年中国齿轮离心鼓风机行业研究报告.docx

    2024年中国齿轮离心鼓风机行业研究报告

    python教程-03-标签属性的获取和设置.ev4.rar

    python教程-03-标签属性的获取和设置.ev4.rar

    狂雨小说CMS-多功能小说系统

    安装说明 系统要求 PHP要求5.6版本以上,低于5.6版本无法运行 支持php7 addons,application,config,extend,public,runtime,template,uploads 目录必须要有写入权限 777 网站必须配置好伪静态(.htaccess为Apache伪静态配置文件,kyxscms.conf为Nginx伪静态配置文件) 宝塔面板要在 软件 php 设置里安装扩展 fileinfo

    基于java的高校毕业设计选题管理系统论文.docx

    基于java的高校毕业设计选题管理系统论文

    信创微服务平台建设指南(PDF)

    当前,以微服务、DevOps、容器、多云业务管理为代表的云原生技术已经广泛成熟应用,成为加速企业数字化业务高效创新、实现企业数字化转型的最佳技术支撑。而信创支持、国产化支持,是中国企业数字化转型不得不满足的基本要求。更有专家指出,在关乎企业生存的必选项“数字化转型”以及国家信创战略的共同冲击下,企业需要改变现有业务和IT的架构,更快速地应对挑战、响应变化,增强自身的竞争力。 信创微服务平台建设指南应当综合考虑当前的技术发展趋势、企业及用户的需求,以及平台的可持续发展能力。 《信创微服务平台建设指南》可参考文章:https://mp.weixin.qq.com/s/cfJH72JFxDTHCPsfFWMUqA

    node-v8.14.0-linux-ppc64le.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    Python爬虫.pdf

    上文提供了一个基础的Python爬虫示例,旨在从CSDN(一个知名的技术博客平台)上爬取特定文章的内容。这个示例代码展示了使用requests库发送HTTP请求,以及使用BeautifulSoup库解析HTML内容的基本流程。 步骤详解 导入必要的库: requests库用于发送HTTP请求。 BeautifulSoup库用于解析HTML内容。 time库用于控制请求之间的延迟。 设置目标URL和请求头: 目标URL是想要爬取的CSDN文章的URL,这里用占位符'https://blog.csdn.net/some_user/article/details/some_article_id'表示,实际使用时需要替换为真实的URL。 请求头(headers)通常用于模拟浏览器行为,避免被目标网站识别为爬虫。这里设置了User-Agent字段。 发送请求并获取响应内容: 使用requests.get()方法发送GET请求到目标URL,并传入请求头。 使用response.raise_for_status()方法检查请求是否成功。如果响应状态码不是200(成功),则抛出异常。 解析HTML内

    node-v8.2.0-linux-ppc64le.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    毕业设计写作技巧.pdf

    说明: 上文提供了一份关于毕业设计论文写作技巧的总结,旨在帮助学生在完成这一重要学术任务时更加系统、高效地进行。以下是对这份总结的详细说明: 一、目的与重要性 毕业设计论文不仅是学生学术生涯中的一个重要里程碑,也是检验学生综合运用所学知识、独立研究和解决问题能力的重要标准。因此,掌握一定的写作技巧对于顺利完成论文写作至关重要。 二、写作技巧总结 明确研究主题和目标: 学生首先需要确定自己的研究领域和研究方向,确保研究的主题具有实际意义和研究价值。 明确研究目标有助于学生在整个研究过程中保持清晰的方向,确保研究的深入和全面。 充分收集和整理资料: 学生需要通过广泛阅读相关领域的文献,了解研究现状和发展趋势,为论文写作提供充分的理论支撑。 对收集到的资料进行整理和分类,有助于提取有用信息,为论文写作提供有力的论据和支撑。 撰写论文大纲: 论文大纲是论文写作的蓝图,它有助于学生清晰地规划论文的结构和内容。 通过制定合理的大纲,学生可以在写作过程中保持逻辑严密、条理清晰。 论文写作注意事项: 引言部分需要简要介绍研究背景、意义、目的和范围,引起读者的兴趣。 正文部分需要详细阐述研究方

    node-v9.6.1-darwin-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    单片机开发资源:基于51单片机的开发程序

    单片机开发资源,基于51单片机的开发程序,供学习参考。

Global site tag (gtag.js) - Google Analytics