如何创建合理的ES索引以兼顾可索引性与存储优化?
问题
需要为以下结构的数据创建Elasticsearch索引:
{ "company_id": uuid, // 需可索引 "author_id": uuid, // 需可索引 "image_url": str, "created_at": datetime, // 需可索引 "text": array // 需可索引 }
其中text字段是动态可变的多语言键值对数组,示例如下:
en => Hello fr => Bonjour
或
ru => Привет hy => Բարև
手动配置的映射代码如下:
$params = [ 'index' => 'posts_index', 'body' => [ 'mappings' => [ 'properties' => [ 'text' => [ 'type' => 'object', 'properties' => [] ], 'company_id' => [ 'type' => 'keyword', 'index' => true, ], 'author_id' => [ 'type' => 'keyword', 'index' => true, ], 'image_url' => [ 'type' => 'text', 'index' => false, ], 'created_at' => [ 'type' => 'date', 'index' => true, 'format' => 'yyyy-MM-dd HH:mm:ss' ], 'updated_at' => [ 'type' => 'date', 'index' => false, 'format' => 'yyyy-MM-dd HH:mm:ss' ], ], ], ], ];
创建11000条测试数据后,该索引占用约36MB;但不手动设置映射直接导入数据时,索引仅占用约21MB,且所有字段都可索引。现在需要在保证指定字段可索引的前提下,尽可能节省存储。
解决方案
1. 修正text字段的映射配置
当前把text设为object且空properties,ES会为每个动态新增的语言字段自动创建text+keyword子字段,额外占用存储。改为使用动态模板,针对text下的所有子字段按需配置,减少冗余:
$params = [ 'index' => 'posts_index', 'body' => [ 'mappings' => [ 'dynamic_templates' => [ [ 'text_languages' => [ 'path_match' => 'text.*', 'mapping' => [ 'type' => 'text', 'norms' => false, // 无需评分时关闭,节省存储 'index_options' => 'freqs' // 仅存储词频,减少倒排索引体积 ] ] ] ], 'properties' => [ 'company_id' => [ 'type' => 'keyword', 'index' => true ], 'author_id' => [ 'type' => 'keyword', 'index' => true ], 'image_url' => [ 'type' => 'keyword', // 用keyword比text更省空间,无需分词 'index' => false ], 'created_at' => [ 'type' => 'date', 'index' => true, 'format' => 'yyyy-MM-dd HH:mm:ss' ], 'updated_at' => [ 'type' => 'date', 'index' => false, 'format' => 'yyyy-MM-dd HH:mm:ss', 'doc_values' => false // 不索引也无需聚合排序,关闭节省空间 ], ], ], ], ];
2. 利用自动映射优势,手动锁定核心字段
自动映射时ES会根据数据类型自动优化(比如uuid识别为keyword、日期自动匹配格式),可以只手动配置需要严格控制的字段,其余让ES自动处理,同时限制冗余字段:
$params = [ 'index' => 'posts_index', 'body' => [ 'mappings' => [ 'dynamic' => 'strict', // 仅允许手动配置的字段,避免意外新增冗余字段 'properties' => [ 'company_id' => ['type' => 'keyword', 'index' => true], 'author_id' => ['type' => 'keyword', 'index' => true], 'created_at' => ['type' => 'date', 'format' => 'yyyy-MM-dd HH:mm:ss'], 'text' => ['type' => 'object', 'dynamic' => true], // 允许text下动态新增语言字段 'image_url' => ['type' => 'keyword', 'index' => false], 'updated_at' => ['type' => 'date', 'index' => false, 'doc_values' => false] ] ] ] ];
这种方式既保证指定字段的索引规则,又借助ES自动优化text子字段的映射,避免手动配置带来的冗余。
3. 索引级别额外优化
- 合并分段:测试数据导入完成后,执行
force_merge操作合并索引分段,减少存储占用(注意不要在生产写入高峰期执行)。 - 调整副本数:测试环境可将
number_of_replicas设为0,生产环境按需设置,副本会占用额外存储。
内容的提问来源于stack exchange,提问作者Alexey Khachatryan
相关产品推荐
相关产品推荐

