Noticing your searches are slow or getting “canceled” or “skipped”? Has your friendly Splunk administrator reported to you that Splunk is flagging your queries as “inefficient”?
Below are a few tips for improving/optimizing your search(es) that we want to highlight for our environment. The essential principle for all of the below is … “reduce, reduce, reduce”.
Also, please read this very helpful document on this topic from Splunk:
Contents
Specify Index(es)
index=apps-myapp_myunit
If you (or anyone else who might be running your search) have access to many indexes, be sure to start your search with an index filter.
INFO: The way Splunk is built, “indexes” are not just metadata values, they’re objects in their own filesystem directories. Failing to specify what index to search forces splunk to plow through the filesystem (the index directories you have access to) for matches to your search terms. If you have access to 21 indexes (typically, if you have access to it, it is included in your “default” set of indexes), specifying an index will help Splunk avoid plowing through every one of those directories. Upshot: It’s *always* good to specify index.
Add Splunk metadata filters early
sourcetype=cisco:asa host=vpn4g*
Splunk has certain “metadata” values that are “indexed”. (These are indexed in files that sit within those ‘index’ directories in filesystem mentioned above.)
- time (_time)
- index
- sourcetype
- host (here at Illinois, we’ve also added indexed field “forwarder” for intermediary forwarders)
- source
It’s not *required* to use one or more of these metadata fields in your search, but wherever one of these *can* be used, it will help Splunk reduce its effort to find matches to your search terms. I.e., adding sourcetype=juniper to index=network-wired_techsvc at the beginning of your search could significantly reduce the amount of things Splunk has to match against. Upshot: Use metadata restrictions whenever it can help reduce.
To figure out what metadata fields you can add to your search to improve efficiency…
- Run the more generic search in Verbose mode (over a short period of time – or hit Stop button after collecting enough events)
- Use the left pane to browse (click on) metadata fields (listed above) to identify a value or values that would help Splunk reduce your search without being overly restrictive.
- Click on the item and then on “add to your search” to add it to your search (or add it manually).
- Save search.
Avoid wildcard prefixes
| Works (But not optimal) | Optimized (more specific) |
|---|---|
| source=*switches* | source=/A/switches/* OR source=/B/switches/* OR source=/C/switches/* OR source=/D/switches/*… or …source IN (/A/switches/*,/B/switches/*,/C/switches/*,/D/switches/*) |
Splunk will let you be as open-ended as possible with wildcards and wildcard prefixes… But if you’re searching a lot of data, a wildcard by itself or as a prefix forces Splunk to search all possible matches. Upshot: Be as specific as possible, and try to avoid using wildcards at the beginning of a string.
(See TIP in item immediately below for more ways to match against many values.)
Avoid NOT
Similar to the above concept, multiple, positive assertions like…
index=myweblogs status=50* OR status=404 OR status=403
are far more efficient than …
index=myweblogs NOT status=202
The latter forces Splunk to evaluate (initially include) every instance of status to make sure it’s not “202”. A positive assertion allows Splunk to evaluate (initially include) only the events with the matching values.
TIP: If you have a lot of positive assertions to match against, there are some tricks to make it easier than a bunch of successive OR statements.
- Use the IN operator (IN is case sensitive!). For example, the above could also be represented with…
status IN (50*,404)
- Store your (positive) matching values in a lookup (csv) file and reference it in a lookup (subsearch):
(Where below the lookup file is “acceptablestatuses.csv” and where “status” is the header of the field with the values we want to match on.)
index=myindex [| inputlookup acceptablestatuses.csv | fields status]
- Very similar to the above, but uses a regular subsearch instead of a lookup file to return the desired set of values.
index=myindex [search index=someindex action=success status=* | fields status]
Get familiar with Lispy (or “How to think like Splunk”)
One of the almost-magical things about Splunk is how fast it can get results from data stored in a very traditional, (relatively) unstructured way across many “buckets” on the filesystem. To optimize your searches, it helps to know how Splunk’s indexing works.
First, on ingest of data, Splunk evaluates each event string to create a list of “keywords” from it (these keywords, with links back to the original event, Splunk calls “tokens”). To “segment” the string in to keywords, it uses “Major” and “Minor” “breakers”:
Major Breakers:
[ ] < > ( ) { } | ! ; , ' " * n r s t & ? + %21 %26 %2526 %3B %7C %20 %2B %3D -- %2520 %5D %5B %3A %0A %2C %28 %29
Minor Breakers:
/ : = @ . -
nbsp; % \ _
In the following example, the green bars denote keywords generated from minor breakers and the blue bars denote keywords from major breakers.
OBSERVE: Notice case of keywords. Notice order of keywords. Notice how both major segments and minor segments are represented in the list of keywords.
| Original event text (showing segmentation) | List of keywords produced in index file from the text to the left
|
|---|---|
|
| 0 0200 03 1 11 127 127.0.0.1 18 2016 24 24/jun/2016:18:11:03.404 404 jun mm |
Using the event and corresponding list of keywords above as a reference, the sample searches below help describe how Lispy is used for an initial filter (reduction).
| SPL search | base Lispy | Result | Note / Explanation |
|---|---|---|---|
| index=myindex 200 |
[ AND 200 index::myindex ] | <!> This will not match (return) the event. | “200” is not a keyword linked to the event. (See list of keywords above.) |
| index=myindex 0200 |
[ AND 0200 index::myindex ] | This will match (return) the event. | “0200” is a keyword linked to the event. |
| index=myindex Jun 24 2016 |
[ AND 2016 24 index::myindex jun ] | This will match (return) the event. | This will match the event – and all other events that also contain all three discrete keywords “2016”, “24”, and “jun”. |
| index=myindex 24/Jun/2016 |
[ AND 2016 24 index::myindex jun ] | This will match (return) the event. | This will match the event – and all other events that also contain all three discrete keywords “2016”, “24”, and “jun”. (Note this is the same lispy as the previous one.) |
| index=myindex “24/Jun/2016” |
[ AND 2016 24 index::myindex jun ] | This will match (return) the event. | This will match the event – and all other events where these keywords (“2016”, “24”, “jun”) exist in the specified sequence with the specified delimiters. But note that this lispy is the same as the previous one. The lispy-based reduction will be the same as the two prior examples; the further reduction of events based on order of keywords and delimiters (“/”) is applied after the base lispy reduction. |
| index=myindex 127.0.0.1 |
[ AND 0 1 127 index::myindex ] | This will match (return) the event. | Note that this may return results *beyond* what you are expecting – because it’s returning results not for the major segment keyword (127.0.0.1), but for any event that has each of the minor segment keywords anywhere in the event (and in any order). (See subsequent rows for more understanding.) * |
| index=myindex “127.0.0.1” |
[ AND 0 1 127 index::myindex ] | This will match (return) the event. | This could be effective at returning the desired events, but may not be as performant as the example immediately below. The performance impact is because the initial lispy-based reduction is including matches not for the major segment keyword (“127.0.0.1”), but for any event that has each of the minor segment keywords anywhere in the event. Consequently, the initial lispy-based reduction would include the same set as the prior example. The further reduction of events based on order of keywords and delimiter (.) is applied after the base lispy reduction. * |
| index=myindex TERM(127.0.0.1) |
[ AND 127.0.0.1 index::myindex ] | This will match (return) the event. | More performant than sample(s) above. The use of TERM() will return events where the string “127.0.0.1” exists as a major segment keyword. (It does exist in this case.) TODO UNHANDLED WIKITAG: <ac_emoticon ac_name=”warning”></ac_emoticon> ENDWIKITAG Note, however, that if the string “127.0.0.1” in the original event string were bound by a minor breaker, for example, “127.0.0.1/23” or “ip=127.0.0.1”, it would not exist as a major segment keyword and this search would therefore not return the event. Lesson: TERM can be powerful, but be sure to know your source data before you use it. * |
| index=myindex 127.0.* |
[ AND 0 127 index::myindex ] | This will match (return) the event. | Note that this may return results *beyond* what you are expecting – because it’s returning any event that has each of the minor segment keywords anywhere in the event (and in any order). * |
| index=myindex “127.0.*” |
[ AND 0 127 index::myindex ] | This will match (return) the event. | This could be effective at returning the desired events. The initial lispy-based reduction would include the same set as the prior example. The further reduction of events based on order of keywords and delimiter (.) is applied after lispy-based reduction. * |
| index=myindex TERM(127.0.0) |
[ AND 127.0.0 index::myindex ] | <!> This will not match (return) the event. | “127.0.0” is not a keyword linked to the event. (See list of keywords above.) * |
| index=myindex TERM(127.0.*) |
[ AND 127.0.* index::myindex ] | This will match (return) the event. | This could be effective at returning the desired events as long as major segments exist and begin with “127.0.”. * |
How to check base Lispy used in search:
- Run a query and wait for it to complete (or cancel it).
- Select “Inspect Job” from “Job” menu under the search bar (to the right).
- Click on the “search.log” link to open the contents of the search.log file in a browser window.
- Search for “lispy” (CTRL-f or Command-f)
* Note that because searching for IP addresses or full CIDR representations can be a challenge for the reasons described above, Splunk offers a specific CIDR match function which works for both IP addresses and full CIDR values.
