Elasticsearch 索引的基本操作

创建索引

curl -XPUT http://127.0.0.1:9200/myindex -d '
{
    "settings": {
        "index": {
            "number_of_shards": 2,
            "number_of_replicas": 1
        }
    }
}'

创建成果的时候会返回:

{"acknowledged":true,"shards_acknowledged":true}

如果要创建的索引已经存在了,那么上面的创建索引命令会出现400错误:

{
    "error":{
        "root_cause":[
            {
                "type":"index_already_exists_exception",
                "reason":"index [myindex/YJRxuqvkQWOe3VuTaTbu7g] already exists",
                "index_uuid":"YJRxuqvkQWOe3VuTaTbu7g",
                "index":"myindex"
            }
        ],
        "type":"index_already_exists_exception",
        "reason":"index [myindex/YJRxuqvkQWOe3VuTaTbu7g] already exists",
        "index_uuid":"YJRxuqvkQWOe3VuTaTbu7g",
        "index":"myindex"
    },
    "status":400
}

在创建索引的时候,有2个比较重要的参数需要留意一下:

  • number_of_shards 它控制组成索引的分片数(每个分片最多可以存储2^32个文档)
  • number_of_replicas 它控制每个分片的副本数量,一般建议最少设置为1

上面的API调用初始化一个新的索引,这意味着:

  • 索引首先在主节点中创建,然后将其状态传播到集群级别的所有节点。
  • 创建默认映射(空)
  • 所有索引所需的分片都已初始化并准备好接受数据

当然了,索引创建api也容许在创建索引的时候定义mapping,比如下面的例子:

curl -XPOST localhost:9200/myindex -d '
{
    "settings": {
        "number_of_shards": 2,
        "number_of_replicas": 1
    },
    "mappings": {
        "order": {
            "properties": {
                "id": {
                    "type": "keyword",
                    "store": "yes"
                },
                "date": {
                    "type": "date",
                    "store": "no",
                    "index": "not_analyzed"
                },
                "customer_id": {
                    "type": "keyword",
                    "store": "yes"
                },
                "sent": {
                    "type": "boolea+n",
                    "index": "not_analyzed"
                },
                "name": {
                    "type": "text",
                    "index": "analyzed"
                },
                "quantity": {
                    "type": "integer",
                    "index": "not_analyzed"
                },
                "vat": {
                    "type": "double",
                    "index": "no"
                }
            }
        }
    }
}'

删除索引

删除索引,意味着删除删除它的分片,副本,mapping以及数据。具体的api命令:

curl -XDELETE http://127.0.0.1:9200/myindex

如果删除成功:

{"acknowledged":true}

如果索引不存在,那么会出现404错误:

{
    "error": {
        "root_cause": [
            {
                "type": "index_not_found_exception",
                "reason": "no such index",
                "resource.type": "index_or_alias",
                "resource.id": "myindex",
                "index_uuid": "_na_",
                "index": "myindex"
            }
        ],
        "type": "index_not_found_exception",
        "reason": "no such index",
        "resource.type": "index_or_alias",
        "resource.id": "myindex",
        "index_uuid": "_na_",
        "index": "myindex"
    },
    "status": 404
}

有一个比较危险的,一般不建议使用的操作就是一次性删除全部的索引,那就是通过_all或者*

curl -XDELETE http://127.0.0.1:9200/_all

一般都建议在elasticsearch.yml`文件中,增加下面的配置:

action.destructive_requires_name:true

打开或者关闭索引

如果你不想删除数据,但是想节约一些资源,比如cpu,内存等资源,那么可以暂时关闭某些个不用的索引。Elasticsearch容许你打开或者关闭一些索引来使得他们online或者offline

curl -XPOST http://127.0.0.1:9200/myindex/_close
{"acknowledged":true}
curl -XPOST http://127.0.0.1:9200/myindex/_open
{"acknowledged":true}

当索引关闭时,这些索引在集群上没有开销(元数据状态除外):索引分片已关闭,并且不使用文件描述符,内存或线程。
关闭索引时有很多用例:

  • 禁用基于日期的索引(按日期存储记录的索引),例如,当您保留一周,一个月或一天的索引,并且希望保留固定数量的旧索引(即两个月)在线 和一些离线(即从两个月到六个月)。
  • 当您对集群的所有活动索引进行搜索,并且不想在某些索引中进行搜索(在这种情况下,使用别名是最佳解决方案,但是通过关闭某些索引页可以达到同样的目的)。

在索引中创建mapping

在索引中创建mapping,就好像在mysql中创建了一个表一样

curl -XPUT 'http://localhost:9200/myindex/order/_mapping' -d '
{
    "order": {
        "properties": {
            "id": {
                "type": "keyword",
                "store": "yes"
            },
            "date": {
                "type": "date",
                "store": "no",
                "index": "not_analyzed"
            },
            "customer_id": {
                "type": "keyword",
                "store": "yes"
            },
            "sent": {
                "type": "boolean",
                "index": "not_analyzed"
            },
            "name": {
                "type": "text",
                "index": "analyzed"
            },
            "quantity": {
                "type": "integer",
                "index": "not_analyzed"
            },
            "vat": {
                "type": "double",
                "index": "no"
            }
        }
    }
}'

如果mapping创建成果,es会返回:

{"acknowledged":true}

上面的创建索引的方式,首先会检查是否已经存在了这个索引,然后在根据定义创建mapping。如果在插入mapping的期间,这个type已经存了mapping,那么就会
发生mapping的merge行为。如果在merge过程中,如果同样的字段但是不同类型,而且这些类型也不能兼容,那么就会出现异常。为了避免出现merge异常,可以通过设置ignore_conflicts为true,默认为false。
截止到目前,es并没有提供删除mapping的功能,为了删除或者修改mapping,需要做下面的事情:
– 创建一个新的索引以及修改过的或者新建的mapping
– 把之前mapping的数据迁移过去
– 删除之前的索引和mapping
在Elasticsearch5.x的版本中,提供了一个新的操作来加速上面的处理步骤:reindex

获取mapping

为了获取mapping,可以通过下面的命令:

curl -XGET http://<server>/_mapping
curl -XGET http://<server>/<index_name>/_mapping
curl -XGET http://<server>/<index_name>/<type_name>/_mapping

索引Reindexing

有很多常见的情况需要更改mapping。 由于对Elasticsearch映射的限制,也就是说,无法删除定义的映射,所以您经常需要重新编索引索引数据。
下面的例子展示了如何从索引myindex重建到myindex2索引

curl -XPOST 'http://localhost:9200/_reindex?pretty=true' -d '
{
    "source": {
        "index": "myindex"
    },
    "dest": {
        "index": "myindex2"
    }
}'

重建成功以后,es会给出类似的结果:

{
    "took": 66,
    "timed_out": false,
    "total": 2,
    "updated": 0,
    "created": 2,
    "deleted": 0,
    "batches": 1,
    "version_conflicts": 0,
    "noops": 0,
    "retries": {
        "bulk": 0,
        "search": 0
    },
    "throttled_millis": 0,
    "requests_per_second": "unlimited",
    "throttled_until_millis": 0,
    "failures": []
}

在server,reindex操作的具体实现步骤如下:
– 初始化一个es任务来管理这个操作
– 创建目标索引,如果需要的话需要复制原始的mapping
– 在原始的mapping中收集需要被重建的数据
– 同步bulk操作来重建全部的数据
更多关于reindex细节,可以参见官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-reindex.html

Refreshing索引

es容许强制刷新索引,否则的话,新插入索引中的数据在将会在一段时间(默认是一秒)以后才可以被搜索。
为了刷新索引,可以使用下面的命令:

curl -XPOST 'http://localhost:9200/myindex/_refresh'

刷新成功以后的结果为:

{"_shards":{"total":4,"successful":2,"failed":0}}

一般都是在索引了很多的数据以后,才会强制刷新一次。当然了也可以在索引文档的时候增加refresh=true来强制刷新索引:

curl -XPOST 'http://localhost:9200/myindex/order/2qLrAfPVQvCRMe7Ku8r0Tw?refresh=true' -d '
{
    "id": "1234",
    "date": "2013-06-07T12:14:54",
    "customer_id": "customer1",
    "sent": true,
    "in_stock_items": 0,
    "items": [
        {
            "name": "item1",
            "quantity": 3,
            "vat": 20
        },
        {
            "name": "item2",
            "quantity": 2,
            "vat": 20
        },
        {
            "name": "item3",
            "quantity": 1,
            "vat": 10
        }
    ]
}'

Flushing 索引

出于性能原因,弹性搜索将一些数据存储在内存和事务日志中。 如果我们要释放内存,清空事务日志,并确保我们的数据安全地写在磁盘上,我们需要刷新索引。
Elasticsearch自动提供在磁盘上的定期刷新,但是强制flush可能是有用的,例如:当我们需要关闭一个节点以防止陈旧的数据要使所有的数据都处于安全状态(例如,在进行大量索引操作以使所有数据刷新和刷新之后)

curl -XPOST 'http://localhost:9200/myindex/_flush? refresh=true'
{"_shards":{"total":4,"successful":2,"failed":0}}

索引ForceMerge

Elasticsearch核心基于Lucene,它将数据存储在磁盘上。 在索引的生命周期中,创建和更改了许多segments。 随着segments的增加,搜索速度由于读取所有时间所需的时间而减少。 ForceMerge操作允许我们整合索引以更快的搜索性能和减少分段。

curl -XPOST 'http://localhost:9200/myindex/_forcemerge'

执行成功以后的结果为:

{
    "_shards": {
        "total": 10,
        "successful": 5,
        "failed": 0
    }
}

Lucene将您的数据存储在磁盘上的几个segmen中。当您索引新的文档/记录或删除文档时,会创建这些段。在es中,删除的文档不会从磁盘中删除,但标记为已删除(tombstone),为了释放空间需要执行ForceMerge操作。

检查index或者type是否存在

curl -i -XHEAD 'http://localhost:9200/myindex/'
curl -i -XHEAD 'http://localhost:9200/myindex/order/'

如果存在的话,http状态码是200,如果不存在的话,http状态码是404

索引收缩(Shrinking an index)

在最新版本的Elasticsearch中提供了一个新的方式来优化索引,通过shrink API可以减少索引的分片数量。
shrink API允许您将现有索引缩小到具有较少主分片的新索引。目标索引中所请求的主碎片数量必须是源索引中碎片数量的一个因子。例如,具有8个主分片的索引可以缩小为4个,2个或1个主分片,或者具有15个主分片的索引可以缩小为5,3或1.如果索引中的分片数量是素数,则可以只能缩小成单个的主碎片。收缩之前,索引中每个分片的(主要或副本)副本必须存在于同一个节点上。
这个api重要针对的目标场景为:

  • 在设计的初期,分片的数量设置的不太合理。 因为通常在刚刚开始的时候是不知道正确的数据/文本分发的情况的,这个一般都会设置较多的分片数量
  • 减少分片数量可以减少内存和资源使用量
  • 减少分片数量可以加快搜索速度

这个api的格式为:

curl -XPOST http://<server>/<source_index_name>/_shrink/<target_index_name>

shrink API工作原理如下:

  • 首先,它创建与源索引具有相同定义的新目标索引,但是具有较小数量的主分片。
  • 然后,将来自源索引的segments硬链接到目标索引中。 (如果文件系统不支持硬链接,则所有segments都将复制到新索引中,这是一个更耗时的过程。)
  • 最后,它恢复了目标索引,好像它是一个刚被重新打开的索引一样。
    为了缩小索引,索引必须标记为只读,并且索引中每个分片的(主副本)副本必须重定位到同一节点并具有运行状况为绿色
    为了满足这两个条件,我们可以通过下面的请求:

    curl -XPUT 'localhost:9200/my_source_index/_settings?pretty' -H 'Content-Type: application/json' -d'
    {
      "settings": {
        "index.routing.allocation.require._name": "shrink_node_name",
        "index.blocks.write": true
      }
    }
    '
    

下面我们简单的介绍一下这个api:

  • "index.routing.allocation.require._name": "shrink_node_name", 这一行呢,强制将每个分片的副本重定位到名称为shrink_node_name的节点。(在下面的具体操作过程中,有介绍如何获取这个节点名称)
  • "index.blocks.write": true 防止对此索引的写入操作,同时仍允许元数据更改,如删除索引。

重新定位源索引可能需要一段时间。 可以使用_cat recovery API跟踪进度,或者可以使用cluster health API等待所有碎片已经通过wait_for_no_relocating_shards参数重新定位。
上面的那个api执行,需要指定一个节点名称,而节点名称可以通过_nodes API检索它:

curl -XGET 'http://localhost:9200/_nodes?pretty'

这个api会返回类似于下面的数据:

....
"nodes" : { "5Sei9ip8Qhee3J0o9dTV4g" : { "name" : "Gin Genie", "transport_address" : "127.0.0.1:9300", "host" : "127.0.0.1", "ip" : "127.0.0.1", "version" : "5.0.0-alpha4", ....

从返回的结果来看,这个node的名称为Gin Genie ,有了节点名称以后,之前的那个更改设置的命令就是:

curl -XPUT 'localhost:9200/my_source_index/_settings?pretty' -H 'Content-Type: application/json' -d'
{
  "settings": {
    "index.routing.allocation.require._name": "Gin Genie",
    "index.blocks.write": true
  }
}
'
  • 我们需要检查是否所有的分配都已经被重新定位,我们可以查看绿色的状态:
    curl -XGET 'http://localhost:9200/_cluster/health?pretty'

结果将会返回:

{
    "cluster_name": "ESCookBook3",
    "status": "green",
    "timed_out": false,
    "number_of_nodes": 2,
    "number_of_data_nodes": 2,
    "active_primary_shards": 15,
    "active_shards": 15,
    "relocating_shards": 0,
    "initializing_shards": 0,
    "unassigned_shards": 15,
    "delayed_unassigned_shards": 0,
    "number_of_pending_tasks": 0,
    "number_of_in_flight_fetch": 0,
    "task_max_waiting_in_queue_millis": 0,
    "active_shards_percent_as_number": 50
}
  • 然后我们需要通过下面的方式来禁止索引的写操作:
    curl -XPUT 'http://localhost:9200/myindex/_settings? index.blocks.write=true'

  • 然后我们执行shrink API操作

    curl -XPOST 'http://localhost:9200/myindex/_shrink/reduced_index' -d '
    {
        "settings": {
            "index.number_of_replicas": 1,
            "index.number_of_shards": 1,
            "index.codec": "best_compression"
        },
        "aliases": {
            "my_search_indices": {}
        }
    }'
    

    执行成功以后会返回:

    {"acknowledged":true}

一旦将目标索引添加到集群状态,上述请求将立即返回,它不等待收缩操作启动。
需要注意的是,只有当满足下面的情况的前提下,才可以缩小索引:

  • 目标索引不能存在
  • 当前的索引必须比目标索引有更多的主碎片。
  • 目标索引中的主分片数量必须是源索引中主分片数的一个因子,比如3是6的因子。 源索引必须具有比目标索引更多的主分片。
  • 当前索引所有分片中的文档总数不能超过2,147,483,519个文档,因为这些文档将缩小到目标索引中的单个分片中,而2,147,483,519是适合单个分片的文档的最大数量
  • 处理收缩过程的节点必须具有足够的可用磁盘空间以容纳当前索引的第二个副本

管理索引的设置

获取索引设置的api的格式为:

curl -XGET http://<server>/<index_name>/_settings

比如:

curl -XGET 'http://localhost:9200/myindex/_settings? pretty=true'
返回结果:
{
    "myindex": {
        "settings": {
            "index": {
                "uuid": "pT65_cn_RHKmg1wPX7BGjw",
                "number_of_replicas": "1",
                "number_of_shards": "2",
                "version": {
                    "created": "1020099"
                }
            }
        }
    }
}

当然,可以通过获取多个索引的设置:

curl -XGET 'localhost:9200/twitter,kimchy/_settings?pretty'
curl -XGET 'localhost:9200/_all/_settings?pretty'
curl -XGET 'localhost:9200/log_2013_*/_settings?pretty'

我们也可以使用通配符匹配对返回的设置进行过滤,如下所示:

curl -XGET 'http://localhost:9200/2013-*/_settings/index.number_*'

为了更新索引的设置,我们可以使用下面的例子:

curl -XPUT 'localhost:9200/twitter/_settings?pretty' -H 'Content-Type: application/json' -d'
{
    "index" : {
        "number_of_replicas" : 2
    }
}
'

Elasticsearch提供了很多选项来调整索引行为,如:副本管理:

  • index.number_of_replicas:每个碎片的副本数量
  • ndex.auto_expand_replicas:这允许您定义与分片数量相关的动态数量的副本

index.auto_expand_replicas设置为0-all可以创建一个在每个节点中复制的索引(对设置或集群传播的数据(如语言选项/停用词)非常有用)。
refresh_interval参数允许一些技巧来优化索引速度。 它控制刷新和刷新的速度,并减少由于打开和关闭文件而导致的索引性能。 一个很好的做法是在大批量索引期间禁用刷新间隔(设置为-1),并在之后恢复默认行为。 这可以通过以下步骤完成:

  • 禁用自动刷新
    curl -XPOST 'http://localhost:9200/myindex/_settings' -d ' {"index":{"index_refresh_interval": "-1"}}'
    
  • 进行文档的批处理操作
  • 恢复自动刷新
    curl -XPOST 'http://localhost:9200/myindex/_settings' -d ' {"index":{"index_refresh_interval": "1s"}}'
    
  • 可选的,您可以优化索引来提升搜索性能:
    curl -XPOST 'http://localhost:9200/myindex/_optimize'

索引重命名

Rollover an index

本文版权归作者所有,禁止一切形式的转载,复制等操作
赞赏

微信赞赏支付宝赞赏

发表评论

电子邮件地址不会被公开。 必填项已用*标注