关系型数据库的范式设计
- 范式
- 1NF-消除非主属性对键的部分函数依赖
- 2NF-消除非主要属性对键的传递函数依赖
- 3NF-消除主属性对键的传递函数依赖
- BCNF-主属性不依赖于主属性
概念
- 范式化设计的主要目标是 减少不必要的更新
- 副作用:查询缓慢,多表联查
- 范式化虽节省空间,但存储越来越便宜
ES反范式-嵌套对象
post my_movies/_doc/1
{
"title":"Speed",
"actors":[
{"first_name":"keanu","last_name":"Reeves"},
{"first_name":"Dennis","last_name":"Hopper"}
]
}
// JSON格式呗处理成扁平式键值对的结构
// 这个文档的存储:
"title":"Speed"
"actors.first_name":["keanu","Dennis"]
"actors.last_name":["Reeves","Hopper"]
nested Data Type
- 允许对象数组中的对象被独立索引
- nested文档会被保存在两个Lucene文档中,在查询时做join处理
- 每次更新,需要重新索引整个对象(包括根对象和嵌套对象)
put my_movies
{
"mappings":{
"properties":{
"actors":{
"type":"nested",
"properties":{
"first_name":{"type":"keyword"},
"last_name":{"type":"keyword"}
}
},
"title":{
"type":"text",
"fields":{
"keyword":{
"type":"keyword",
"ignore_above":256
}
}
}
}
}
}
// nested 查询
post my_movie/_search
{
"query":{
"bool":{
"must":[
{"match":{"title":"Speed"}},
{
"nested":{
"path":"actors",
"query":{
"bool":{
"must":[
{"match":{"actors.first_name":"Keanu"}}
]
}
}
}
}
]
}
}
}
示例
PUT /test_spu
{
"mappings": {
"properties": {
"spu_name":{
"type": "text",
"null_value": "null"
},
"skus":{
"type": "nested",
"properties": {
"sku_name":{
"type":"text"
}
}
}
}
}
}
父子文档
ES提供类似关系型数据库的Join实现,可以维护父子关系
- 父文档和子文档是两个独立的文档
更新父文档无需重新索引子文档。子文档被添加、更新或者删除也不会影响到父文档和其他子文档
// 设置mapping
put my_blogs
{
"mappings":{
"properties":{
"blog_comments_relation":{
"type":"join",
"relations":{
"blog":"comment" -- parent名称:child名称
}
}
}
}
}
// 索引父文档
put my_blogs/_doc/blog1
{
"title":"ES牛逼",
"content":"bilibili",
"blog_comments_relation":{
"name":"blog" -- 申明文档类型
}
}
// 索引子文档
put my_blogs/_doc/comment1?routing=blog1 -- 指定routing,确保和付文档索引到相同的分片,提高join性能
{
"comment":"说的好",
"username":"张傲霜",
"blog_comments_relation":{
"name":"comment",
"parent":"blog1" -- 父文档id
}
}
// 父查子
//parent_id查询
post my_blogs/_search
{
"query":{
"parent_id":{
"type":"comment",
"id":"blog1"
}
}
}
// has_parent查询
post my_blogs/_search
{
"query":{
"has_parent":{
"parent_type":"blog",
"query":{
"match":{
"title": "java"
}
}
}
}
}
// 子查父
post my_blogs/_search
{
"query":{
"has_child":{
"type":"comment",
"query":{
"match":{
"username":"jack"
}
}
}
}
}
// 访问子文档
get my_blogs/_doc/comment1?routing=blog1
// 更新子文档
put my_blogs/_doc/comment1?routing=blog1
{
"comment":"java is best"
}
示例
//创建索引
PUT /test_spu
{
"mappings": {
"properties": {
"name":{
"type": "text"
},
"relation":{
"type": "join",
"relations":{
"spu":"sku"
}
}
}
}
}
// 索引父文档