[[search-shard-routing]] == Search shard routing To protect against hardware failure and increase search capacity, {es} can store copies of an index's data across multiple shards on multiple nodes. When running a search request, {es} selects a node containing a copy of the index's data and forwards the search request to that node's shards. This process is known as _search shard routing_ or _routing_. [discrete] [[search-adaptive-replica]] === Adaptive replica selection By default, {es} uses _adaptive replica selection_ to route search requests. This method selects an eligible node using <> and the following criteria: * Response time of prior requests between the coordinating node and the eligible node * How long the eligible node took to run previous searches * Queue size of the eligible node's `search` <> Adaptive replica selection is designed to decrease search latency. However, you can disable adaptive replica selection by setting `cluster.routing.use_adaptive_replica_selection` to `false` using the <>. If disabled, {es} routes search requests using a round-robin method, which may result in slower searches. [discrete] [[shard-and-node-preference]] === Set a preference By default, adaptive replica selection chooses from all eligible nodes and shards. However, you may only want data from a local node or want to route searches to a specific node based on its hardware. Or you may want to send repeated searches to the same shard to take advantage of caching. To limit the set of nodes and shards eligible for a search request, use the search API's <> query parameter. For example, the following request searches `my-index-000001` with a `preference` of `_local`. This restricts the search to shards on the local node. If the local node contains no shard copies of the index's data, the request uses adaptive replica selection to another eligible node as a fallback. [source,console] ---- GET /my-index-000001/_search?preference=_local { "query": { "match": { "user.id": "kimchy" } } } ---- // TEST[setup:my_index] You can also use the `preference` parameter to route searches to specific shards based on a provided string. If the cluster state and selected shards do not change, searches using the same `preference` string are routed to the same shards in the same order. We recommend using a unique `preference` string, such as a user name or web session ID. This string cannot start with a `_`. TIP: You can use this option to serve cached results for frequently used and resource-intensive searches. If the shard's data doesn't change, repeated searches with the same `preference` string retrieve results from the same <>. For time series use cases, such as logging, data in older indices is rarely updated and can be served directly from this cache. The following request searches `my-index-000001` with a `preference` string of `my-custom-shard-string`. [source,console] ---- GET /my-index-000001/_search?preference=my-custom-shard-string { "query": { "match": { "user.id": "kimchy" } } } ---- // TEST[setup:my_index] NOTE: If the cluster state or selected shards change, the same `preference` string may not route searches to the same shards in the same order. This can occur for a number of reasons, including shard relocations and shard failures. A node can also reject a search request, which {es} would re-route to another node. [discrete] [[search-routing]] === Use a routing value When you index a document, you can specify an optional <>, which routes the document to a specific shard. For example, the following indexing request routes a document using `my-routing-value`. [source,console] ---- POST /my-index-000001/_doc?routing=my-routing-value { "@timestamp": "2099-11-15T13:12:00", "message": "GET /search HTTP/1.1 200 1070000", "user": { "id": "kimchy" } } ---- You can use the same routing value in the search API's `routing` query parameter. This ensures the search runs on the same shard used to index the document. [source,console] ---- GET /my-index-000001/_search?routing=my-routing-value { "query": { "match": { "user.id": "kimchy" } } } ---- // TEST[setup:my_index] You can also provide multiple comma-separated routing values: [source,console] ---- GET /my-index-000001/_search?routing=my-routing-value,my-routing-value-2 { "query": { "match": { "user.id": "kimchy" } } } ---- // TEST[setup:my_index] [discrete] [[search-concurrency-and-parallelism]] === Search concurrency and parallelism By default, {es} doesn't reject search requests based on the number of shards the request hits. However, hitting a large number of shards can significantly increase CPU and memory usage. TIP: For tips on preventing indices with large numbers of shards, see <>. You can use the `max_concurrent_shard_requests` query parameter to control maximum number of concurrent shards a search request can hit per node. This prevents a single request from overloading a cluster. The parameter defaults to a maximum of `5`. [source,console] ---- GET /my-index-000001/_search?max_concurrent_shard_requests=3 { "query": { "match": { "user.id": "kimchy" } } } ---- // TEST[setup:my_index] You can also use the `action.search.shard_count.limit` cluster setting to set a search shard limit and reject requests that hit too many shards. You can configure `action.search.shard_count.limit` using the <>.