Splunk: 統計値が2倍になる?マルチバリューのカウントと検索に関する注意点

たまたま発生したのでメモ。

###### 実施環境： Splunk Free 8.2.2

###### 発生した事象

以下のようなデータを考えます。

|STR|
|:-----|
|AAA AAA|

```Splunk:Splunk
| makeresults count=1
| eval STR = "AAA,AAA"
| makemv delim="," STR
```

![スクリーンショット 2022-02-06 22.27.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/5567b05c-d469-fa16-caab-f88ac30e2bf5.png "multivalue")

これについて stats コマンドの count 関数を使用して件数を集計すると、1という結果が出ます。

```Splunk:Splunk
| makeresults count=1
| eval STR = "AAA,AAA"
| makemv delim="," STR
| stats count
```

![スクリーンショット 2022-02-06 22.27.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/77350fc0-1bf8-59f1-a675-177ae1b5daa6.png "count")

では、以下のように BY で STR 毎の件数を集計するとどうなるでしょうか。
普通に考えれば、先ほどと同じく1となるように思われます。

```Splunk:Splunk
| makeresults count=1
| eval STR = "AAA,AAA"
| makemv delim="," STR
| stats count BY STR
```

ところが、実際に動かしてみると以下のようになります。

![スクリーンショット 2022-02-06 22.28.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/d9794385-8567-78cf-bcc7-b844c94e0229.png "count_by")

先ほどと異なり、結果は__「2」__になります。
なぜこのようなことが起こるのでしょうか。

###### 原因

原因は、「マルチバリュー」にあります。
 stats コマンドで BY を指定した際、同コマンドは「個別の値ごとに1つの行を返す」のですが、マルチバリューは含まれる値全てセットで「個別の値」ではなく、含まれる値__それぞれが__「個別の値」として扱われます。
すなわち、上記の例を用いると、

__STR = AAA, AAA__

ではなく、

__STR = AAA, STR = AAA__

といった感じになるのです。

検索での動作を見るとわかりやすいです。
マルチバリューでない「 AAA , AAA 」は「 AAA 」とは異なるので検索でヒットしません。

```Splunk:Splunk
| makeresults count=1
| eval STR = "AAA,AAA"
| where STR = "AAA"
```

![スクリーンショット 2022-02-13 13.53.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/d7ff2fc8-cc0d-02b5-2a2b-69d3999205e7.png "no_multi")

しかしこれをマルチバリューにすると、「 AAA 」でヒットするようになります。
これは、「 STR 」の値が「 AAA , AAA 」ではなく「 AAA 」と「 AAA 」だからです。

```Splunk:Splunk
| makeresults count=1
| eval STR = "AAA,AAA"
| makemv delim="," STR
| where STR = "AAA"
```

![スクリーンショット 2022-02-13 13.54.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/206864b6-5ece-88d5-4f7b-a92e053c2a67.png "multi")

マルチバリューの値を異なるものにすると、もっとわかりやすくなります。
以下の例をご覧下さい。

```Splunk:Splunk
| makeresults count=1
| eval STR = "AAA,BBB"
| makemv delim="," STR
| where STR = "AAA" AND STR = "BBB"
```

![スクリーンショット 2022-02-13 13.55.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/3496a5d8-1051-3bb9-804b-9318a7c3dc27.png "multi2")

「 STR が AAA かつ STR が BBB 」は普通に考えれば矛盾した条件であり、1件もヒットするはずはありません。
ですが、マルチバリューにおいては

__STR = AAA, STR = BBB__

すなわち、「 STR が AAA という値と BBB という値を同時にとる」という状況が発生するため、検索にヒットしてしまいます。

###### 対処方法

マルチバリューを使用しないのが一番の対処法ですが、 collect コマンドで重複するフィールドを定義してしまった場合など、実際は思わぬ動作でマルチバリューが発生してしまうことがあります。
そのような状況へのシンプルな対処法として、 stats コマンドや  timechart コマンドの dedup_splitvals オプションを true にするというのがあります。
このオプションはデフォルトでは false なのですが、これを true にするとマルチバリュー内での重複を排除してくれます。

```Splunk:Splunk
| makeresults count=1
| eval STR = "AAA,AAA"
| makemv delim="," STR
| stats dedup_splitvals=true count BY STR
```

![スクリーンショット 2022-02-13 14.04.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/96ace574-efa6-cd6c-5c12-5f7905956331.png "deduce_splitvals")

または、 eval コマンドの mvdedup 関数を使用するという方法もあります。
こちらもマルチバリュー内部での重複を排除する効果があります。

```Splunk:Splunk
| makeresults count=1
| eval STR = "AAA,AAA"
| makemv delim="," STR
| eval STR_TMP = mvdedup(STR)
| stats count BY STR_TMP
```

![スクリーンショット 2022-02-13 14.06.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/094c40bd-2d09-be4f-3fa0-d75e4d85ce7a.png "mvdedup")

ただし、上記はあくまで重複の排除なので、異なる値がマルチバリューとして同時に入っている場合は対応できません。

```Splunk:Splunk
| makeresults count=1
| eval STR = "AAA,BBB"
| makemv delim="," STR
| stats dedup_splitvals=true count BY STR
```

![スクリーンショット 2022-02-13 14.08.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/668e5814-e606-4dc1-3cd5-788f07dceb2f.png "fail_dedup")

このような場合は、マルチバリューを nomv コマンドで結合して、全てセットで「個別の値」として扱うことで対応可能です。

```Splunk:Splunk
| makeresults count=1
| eval STR = "AAA,BBB"
| makemv delim="," STR
| nomv STR
| stats count BY STR
```

![スクリーンショット 2022-02-13 14.09.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/214fdc3b-7483-0a2f-a791-db2894deeafb.png "nomv")