场景:书有标签,一本书可能有多个标签。一个标签可能对应多本书。
如果是关系型数据库来存储:
create table book(
id int,
title char(20)
)engine myisam charset utf8;
insert into book values(5,'PHP经典'),(6,'Ruby实战'),(7,'MySQL基础'),(8,'Ruby服务端编程');
create table tags(
id int,
book_id int,
content char(20)
)engine myisam charset utf8;
insert into tags values(10,5,'php'),(11,5,'web'),(12,6,'web'),(13,6,'ruby'),(14,7,'database'),(15,8,'ruby'),(16,8,'server');
查询既有web
标签又有php
标签的书:
select * from tags inner join tags as t on tags.id=t1.id
where tags.content='php' and t.content='web';
如果是要查询 既有web标签又有php标签,同时还有database标签的书,你就要三表联查。
如果数据量大了,比如上百万本书,这样的查询就太消耗性能了。(没发玩了)
换思路:用key-value存储
set book-5-title 'PHP经典'
set book-6-title 'Ruby实战'
set book-7-title 'MySQL基础'
使用redis的set集合
类型存储书的标签:
sadd tag-php 5 #tag-php标签对应的 5号书
sadd tag-web 5 6 #tag-web标签对应的 5号和6号书
sadd tag-database 7
sadd tag-ruby 6 8
sadd tag-server 8
查:
既有php标签
又有web标签
的书
sinter tag-php tag-web #集合的交集
有php标签
或web标签
的书
sunion tag-php tag-web #并集
含有ruby标签
但不含web标签
的书
sdiff tag-ruby tag-web #求差集
1、把表名转换为key前缀,如tag:
2、把第二段放置用于区分key的字段,对应msyql中主键的列名,如user_id
3、第三段放置主键值,如2,3,4
4、第四段写存储的列名
用户表uesr,转换为key-value存储
user_id user_name email
9 lily [email protected]
set user:user_id:9:user_name lily
set user:user_id:9:email [email protected]
#查询这个用户
keys user:user_id:9*
注意:
在关系型数据中,除主键外,还有可能其他列也会参与查询。
如上表中,user_name也是很频繁查询的,往往这种列也是加了索引的。
转换到key-value数据中,则也要相应的生成一条按照该列为主的key-value
set user_name:lily:user_id 9
这样我们可以根据user_name:lily:user_id
查询出user_id为9,再查user_id:9:email
。
完成了根据用户名查询用户信息。