ES 14 - (底層原理) Elasticsearch內部如何處理不同type的數據


1 type的作用

在Elasticsearch的索引(index)中, 通過標識元字段_type來區分不同的type, 所以我們可以把具有相同字段(field)的文檔划分到同一個type下.

==> 因而_type也稱作映射類型, 即每個type都有各自的mapping.

但即使是類似的數據, 也有可能存在不同的field, 比如:

商品中有電子商品有電壓field;
服裝商品有洗滌方式field;
生鮮商品有營養成分field… 這些不同的field要如何處理呢?

==> 在之前的博文中有提到過: 同一index的不同type中, 同名的field的映射配置必須相同. 這是為什么呢?

2 type的底層數據結構

Elasticsearch底層所使用的核心工具庫——Lucene中並沒有type的說法, 它在建立索引的時候, 會把所有field的值當做opaque bytes(不透明字節)類型來處理:

在存儲document時, ES會將該document所屬的type作為一個type字段進行存儲;

在搜索document時, ES通過_type來進行過濾和篩選.

每個index中的所有type都是存儲在一起的, 因此:

在Elasticsearch 6.0之前: 同一個index的不同type中, 同名的field的映射配置(_type)必須相同.

在Elasticsearch 6.0開始: 一個index中不能擁有多個type.

3 探究type的存儲結構

說明: 從Elasticsearch 6.0開始, 不允許在一個index中創建多個type ——只能創建一個, 否則將發生錯誤:

{
  "error": {
    "root_cause": [
      {
        "type": "illegal_argument_exception",
        "reason": "Rejecting mapping update to [website] as the final mapping would have more than 1 type: [manager, writer]"
      }
    ],
    "type": "illegal_argument_exception",
    "reason": "Rejecting mapping update to [website] as the final mapping would have more than 1 type: [manager, writer]"
  },
  "status": 400
}

這里演示所用的版本是6.6.0, 特此說明.

3.1 創建索引並配置映射

PUT website
{
    "mappings": {      // Elasticsearch 6.0之后的版本中, 只添加這一個type
        "writer": {
            "properties": {
                "id": { "type": "long" },
                "name": { "type": "text" },
                "age": { "type": "integer" },
                "sex": { "type": "text", "index": false }
            }
        }, 
        "manager": {   // 省去此type
            "properties": {
                "id": { "type": "long" },
                "name": { "type": "text" },
                "age": { "type": "integer" },
                "sex": { "type": "text", "index": false }, 
                "authorize": { "type": "text", "index": false}
            }
        }
    }
}

3.2 添加數據

PUT website/writer/1
{
    "id": 1001,
    "name": "tester",
    "age": 18,
    "sex": "female"
}
// Elasticsearch 6.0之后的版本中, 不添加下述文檔:
PUT website/manager/1
{
    "id": 1001,
    "name": "shou feng",
    "age": 20,
    "sex": "male",
    "authorize": "all"
}

3.3 查看存儲結構

// 搜索所有數據
GET website/_search

// 搜索結果如下:
{
  "hits" : {
    "total" : 1,
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "website",
        "_type" : "writer",    // _type是writer
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "id" : 1001,
          "name" : "tester",
          "age" : 18,
          "sex" : "female"
        }
      },
      {
        "_index": "website",
        "_type": "manager",			// _type為manager
        "_id": "1",
        "_score": 1,
        "_source": {
          "id": 1001,
          "name": "shou feng",
          "age": 20,
          "sex": "male",
          "authorize": "all"
        }
      }
    ]
  }
}

4 關於type的最佳實踐

將結構類似的type存放在同一個index下 —— 這些type的大部分field應該是相同的.

如果將兩個field完全不同的type存入同一個index下, 在Lucene底層存儲時, 每個document中都將有一大部分field是空值, 這將導致嚴重的性能問題, 並且占用磁盤空間:

例如: 上述website/writer的每個document中, 都有"authorize"字段, 只是它們的值都為空.

—— 從這個角度出發, 大概就能猜出 ES限制一個index中只能有一個type 的原因了吧, 也就是更方便地組織文檔數據、節省磁盤空間😊

版權聲明

作者: 馬瘦風

出處: 博客園 馬瘦風的博客

您的支持是對博主的極大鼓勵, 感謝您的閱讀.

本文版權歸博主所有, 歡迎轉載, 但請保留此段聲明, 並在文章頁面明顯位置給出原文鏈接, 否則博主保留追究相關人員法律責任的權利.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM