Microsoft Sentinel 中的 Kusto 查詢語言

Kusto 查詢語言是您將用來處理及操作 Microsoft Sentinel 中資料的語言。 如果您無法分析記錄並取得隱藏在所有資料中的重要資訊,則您饋送至工作區的記錄並不重要。 Kusto 查詢語言不僅具有取得該資訊的強大功能和彈性,而且能協助您快速開始使用的簡單性。 如果您在腳本或使用資料庫方面有背景,本文的許多內容會感到非常熟悉。 如果沒有,別擔心,因為語言的直覺本質可讓您快速開始撰寫自己的查詢,並推動貴組織的價值。

本文介紹Kusto 查詢語言的基本概念,涵蓋一些最常使用的函式和運算子,其中應處理您每天撰寫的 75% 至 80% 的查詢。 當您需要更深入或執行更進階的查詢時,您可以利用適用于 Microsoft Sentinel 活頁簿的新 進階 KQL(請參閱此 簡介部落格文章 )。 另 請參閱官方Kusto 查詢語言檔 以及各種線上課程(如 Pluralsight)。

背景 - 為何Kusto 查詢語言?

Microsoft Sentinel 建置在 Azure 監視器服務之上,並使用 Azure 監視器的 Log Analytics 工作區來儲存其所有資料。 此資料包含下列任一項:

  • 使用 Microsoft Sentinel 資料連線器,從外部來源擷取到預先定義的資料表中的資料。
  • 使用自訂建立的資料連線器以及某些類型的現成連接器,從外部來源擷取到使用者定義的自訂資料表。
  • 由 Microsoft Sentinel 本身建立的資料,由其建立和執行的分析所產生 ,例如警示、事件和 UEBA 相關資訊。
  • 上傳至 Microsoft Sentinel 以協助偵測和分析的資料,例如威脅情報摘要和監看清單。

Kusto 查詢語言已開發為 Azure 資料 總管服務的一部分 ,因此已針對在雲端環境中搜尋巨量資料存放區進行優化。 靈感來自著名的海底探險家雅克·庫斯特奧(並據以「koo-STOH」發音),它旨在協助您深入探索您的資料海洋,並探索其隱藏的寶藏。

Kusto 查詢語言也用於 Azure 監視器(因此在 Microsoft Sentinel 中),包括一些額外的 Azure 監視器功能,可讓您擷取、視覺化、分析和剖析 Log Analytics 資料存放區中的資料。 在 Microsoft Sentinel 中,每當您在現有規則和活頁簿中,或在建置自己的規則和活頁簿中,視覺化和分析資料並搜捕威脅時,您就會使用以Kusto 查詢語言為基礎的工具。

由於Kusto 查詢語言是您在 Microsoft Sentinel 中執行之幾乎所有作業的一部分,因此清楚瞭解其運作方式可協助您從 SIEM 中取得更多功能。

什麼是查詢?

Kusto 查詢語言查詢是處理資料並傳回結果的唯讀要求,它不會寫入任何資料。 查詢會針對組織成資料庫 資料表 和資料 行階層 的資料運作,類似于 SQL。

要求會以純文字表示,並使用資料流程模型,其設計目的是讓語法易於讀取、寫入及自動化。 我們會詳細看到這一點。

Kusto 查詢語言查詢是由以分號分隔的語句 所組成 。 有許多類型的語句,但只有兩種廣泛使用的類型,我們將在這裡討論:

  • 表格式運算式語句是我們談論查詢時通常代表的語句 ,這些是查詢的實際主體。 關於表格式運算式語句的重點是,它們接受表格式輸入(資料表或其他表格式運算式),並產生表格式輸出。 至少需要其中一項。 本文其餘大部分將討論這種陳述。

  • let 語句 可讓您在查詢主體之外建立和定義變數和常數,以便更容易閱讀和多功能。 這些是選擇性的,視您的特定需求而定。 我們將在本文結尾處理這種語句。

示範環境

您可以在 Azure 入口網站 的 Log Analytics 示範環境中 練習Kusto 查詢語言語句,包括本文 中的語句。 使用此練習環境並無費用,但您需要 Azure 帳戶才能存取它。

探索示範環境。 就像生產環境中的 Log Analytics 一樣,它可用於數種方式:

  • 選擇要建置查詢的資料表。 從預設 的 [資料表] 索引標籤(顯示在左上方的紅色矩形中),從依主題分組的資料表清單中選取資料表(左下方所示)。 展開主題以查看個別資料表,您可以進一步展開每個資料表,以查看其所有欄位(資料行)。 按兩下資料表或功能變數名稱會將它放在查詢視窗中資料指標的點。 輸入資料表名稱後面的其餘查詢,如下所述。

  • 尋找要研究或修改的常設查詢。 選取 [ 查詢 ] 索引標籤(顯示在左上方的紅色矩形中),以查看現成可用的查詢清單。 或者,從右上方的按鈕列中選取 [查詢 ]。 您可以探索隨 Microsoft Sentinel 現成可用的查詢。 按兩下查詢會將整個查詢放在資料指標的查詢視窗中。

    Shows the Log Analytics demo environment.

如同在此示範環境中,您可以在 [Microsoft Sentinel 記錄 ] 頁面中查詢和篩選資料。 您可以選取資料表並向下切入以查看資料行。 您可以使用 [資料行選擇器 ] 修改顯示 的預設資料行,而且您可以設定查詢的預設時間範圍。 如果在查詢中明確定義時間範圍,時間篩選將會無法使用(灰色)。

查詢結構

若要開始學習Kusto 查詢語言,最好是瞭解整體查詢結構。 查看 Kusto 查詢時,您會注意到的第一件事是使用管道符號 ( | )。 Kusto 查詢的結構是從從資料來源取得您的資料開始,然後透過「管線」傳遞資料,而每個步驟都會提供某種程度的處理,然後將資料傳遞至下一個步驟。 在管線結束時,您將取得最終結果。 實際上,這是我們的管線:

Get Data | Filter | Summarize | Sort | Select

這個將資料傳遞至管線的概念可讓結構非常直覺,因為您可以輕鬆地在每個步驟中建立資料的精神圖片。

為了說明這一點,讓我們看看下列查詢,其會查看 Microsoft Entra 登入記錄。 當您逐行閱讀時,您可以看到指出資料發生狀況的關鍵字。 我們已在管線中包含相關階段,以作為每一行的批註。

注意

您可以將批註新增至查詢中的任何一行,方法是在查詢前面加上雙斜線 ( // )。

SigninLogs                              // Get data
| evaluate bag_unpack(LocationDetails)  // Ignore this line for now; we'll come back to it at the end.
| where RiskLevelDuringSignIn == 'none' // Filter
   and TimeGenerated >= ago(7d)         // Filter
| summarize Count = count() by city     // Summarize
| sort by Count desc                    // Sort
| take 5                                // Select

因為每個步驟的輸出都會做為下一個步驟的輸入,因此步驟的順序可以判斷查詢的結果並影響其效能。 請務必根據您想要從查詢中取得的內容來排序步驟。

提示

  • 良好的經驗法則是儘早篩選您的資料,因此您只會將相關資料傳遞至管線。 這可大幅提升效能,並確保您不會意外地在摘要步驟中包含不相關的資料。
  • 本文將指出一些要牢記的其他最佳做法。 如需更完整的清單,請參閱 查詢最佳做法

希望您現在對 Kusto 查詢語言 中查詢的整體結構有所瞭解。 現在讓我們看看實際查詢運算子本身,用來建立查詢。

資料類型

在進入查詢運算子之前,讓我們先快速查看 資料類型 。 與大多數語言一樣,資料類型會決定可以針對值執行哪些計算和操作。 例如,如果您有類型為字串 的值 ,您將無法對它執行算術計算。

在Kusto 查詢語言中,大部分的資料類型都遵循標準慣例,而且您以前可能見過的名稱。 下表顯示完整清單:

資料類型資料表

類型 其他名稱(秒) 對等的 .NET 類型
bool Boolean System.Boolean
datetime Date System.DateTime
dynamic System.Object
guid uuid, uniqueid System.Guid
int System.Int32
long System.Int64
real Double System.Double
string System.String
timespan Time System.TimeSpan
decimal System.Data.SqlTypes.SqlDecimal

雖然大部分的資料類型都是標準的,但您可能不太熟悉動態 時間範圍 guid 類型。

Dynamic 的結構與 JSON 非常類似,但有一個主要差異:它可以儲存傳統 JSON 無法Kusto 查詢語言特定資料類型,例如巢狀 動態 值或 時間範圍 。 以下是動態類型的範例:

{
"countryOrRegion":"US",
"geoCoordinates": {
"longitude":-122.12094116210936,
"latitude":47.68050003051758
},
"state":"Washington",
"city":"Redmond"
}

Timespan 是一種資料類型,是指時間量值,例如小時、天或秒。 請勿將時間範圍 datetime 混淆 ,這會評估為實際的日期和時間,而不是時間的量值。 下表顯示時間範圍 尾碼的清單

Timespan 尾碼

函式 描述
D
H 小時
M minutes
S seconds
Ms milliseconds
Microsecond 微秒
Tick 納 秒

Guid 是代表 128 位全域唯一識別碼的資料類型,其遵循標準格式為 [8]-[4]-[4]-[4]-[4]-[12],其中每個 [number] 代表字元數目,而且每個字元的範圍可以從 0-9 或 a-f 不等。

注意

Kusto 查詢語言同時具有表格式和純量運算子。 本文的其餘部分,如果您只看到 「operator」 這個字,您可以假設它表示表格式運算子,除非另有說明。

取得、限制、排序和篩選資料

Kusto 查詢語言的核心詞彙-可讓您完成絕大多數工作的基礎- 是篩選、排序和選取資料的運算子集合。 您需要執行的其餘工作會要求您擴充語言的知識,以符合更進階的需求。 讓我們在上述範例中使用的 一些命令上展開一點,並查看 takesortwhere

針對這些運算子,我們將檢查其在先前 的 SigninLogs 範例中的用法,並瞭解有用的秘訣或最佳做法。

取得資料

任何基本查詢的第一行會指定您想要使用哪一個資料表。 在 Microsoft Sentinel 的情況下,這可能是工作區中的記錄類型名稱,例如 SigninLogs SecurityAlert CommonSecurityLog 。 例如:

SigninLogs

請注意,在Kusto 查詢語言中,記錄檔名稱會區分大小寫,因此 SigninLogssigninLogs 會以不同的方式解譯。 在選擇自訂記錄的名稱時,請小心,因此它們很容易識別,而且與另一個記錄不太類似。

限制資料: 限制 /

take 運算子 (和相同的 限制 運算子) 只會傳回指定數目的資料列,以限制您的結果。 後面接著整數,指定要傳回的資料列數目。 一般而言,在您判斷排序次序之後,它會在查詢結尾使用,在這種情況下,它會傳回排序次序頂端的指定資料列數目。

當您不想要傳回大型資料集時,在查詢稍早使用 take 時,對測試查詢很有用。 不過,如果您在任何 sort 作業之前放置 take 作業, take 則會隨機傳回選取的資料列,而且每次執行查詢時,可能都會傳回不同的一組資料列。 以下是使用 take 的範例:

SigninLogs
      | take 5

Screenshot of results of take operator.

提示

當您在可能不知道查詢外觀的全新查詢上工作時,將語句放在 take 開頭,以人為方式限制資料集以加快處理和實驗的速度會很有用。 一旦您滿意完整的查詢,您就可以移除初始 take 步驟。

排序資料: 排序 / 順序

排序 運算子(和相同的 順序 運算子)用來依指定的資料行排序您的資料。 在下列範例中,我們會依 TimeGenerated 排序結果,並將順序方向設定為以 desc 參數遞減,先放置最高值;針對遞增順序,我們會使用 asc

注意

排序的預設方向是遞減,因此在技術上,您只需要指定是否要以遞增順序排序。 不過,在任何情況下指定排序方向,都會讓您的查詢更容易閱讀。

SigninLogs
| sort by TimeGenerated desc
| take 5

如前所述,我們會將 sort 運算子放在 運算子之前 take 。 我們需要先排序,以確保我們取得適當的五筆記錄。

Screenshot of results of sort operator, with take limit.

前幾個

top 運算子可讓我們將 和 take 作業合併 sort 成單一運算子:

SigninLogs
| top 5 by TimeGenerated desc

如果兩個或多個記錄在您排序依據的資料行中具有相同值,您可以新增更多資料行來排序依據。 在逗號分隔清單中新增額外的排序資料行,位於第一個排序資料行之後,但在排序次序關鍵字之前。 例如:

SigninLogs
| sort by TimeGenerated, Identity desc
| take 5

現在,如果 TimeGenerated 在多個記錄之間相同,則會嘗試依 Identity 資料行中的 值排序。

注意

使用 sorttake 的時機,以及使用時機 top

  • 如果您只排序一個欄位,請使用 top ,因為它提供比 和 take 組合 sort 更好的效能。

  • 如果您需要對多個欄位進行排序(如上述最後一個範例所示), top 則無法這麼做,因此您必須使用 sorttake

篩選資料: 其中

其中 運算子可以說是最重要的運算子,因為它是確定您只處理與案例相關的資料子集的關鍵。 您應該盡最大努力在查詢中儘早篩選資料,因為這樣做會藉由減少後續步驟中需要處理的資料量來改善查詢效能:它也可確保您只對所需的資料執行計算。 請參閱此範例:

SigninLogs
| where TimeGenerated >= ago(7d)
| sort by TimeGenerated, Identity desc
| take 5

運算子 where 會指定變數、比較 ( 純量 ) 運算子和值。 在我們的案例中,我們用來 >= 表示 TimeGenerated 資料行中的 值必須大於(也就是晚于)或等於七天前。

Kusto 查詢語言中有兩種類型的比較運算子:字串和數值。 下表顯示數值運算子的完整清單:

數值運算子

運算子 描述
+ 加法
-
* 乘法
/ 部門
% 模數
< 小於
> 大於
== 等於
!= 不等於
<= 小於或等於
>= 大於或等於
in 等於其中一個專案
!in 不等於任何專案

字串運算子清單是較長的清單,因為它具有區分大小寫、子字串位置、前置詞、尾碼等等的排列。 運算子 == 同時是數值和字串運算子,這表示它可以同時用於數位和文字。 例如,下列兩個語句都是有效的 where 語句:

  • | where ResultType == 0
  • | where Category == 'SignInLogs'

提示

最佳做法: 在大部分情況下,您可能會想要依多個資料行篩選資料,或以多個方式篩選相同的資料行。 在這些情況下,您應該牢記兩個最佳做法。

您可以使用 和 關鍵字,將多個 where 語句合併成單一步驟 。 例如:

SigninLogs
| where Resource == ResourceGroup
    and TimeGenerated >= ago(7d)

當您使用 關鍵字將多個篩選聯結至單 where 一語句時,您會藉由先放置只參考單一資料行的篩選來獲得更好的效能。 因此,撰寫上述查詢的更好方式是:

SigninLogs
| where TimeGenerated >= ago(7d)
    and Resource == ResourceGroup

在此範例中,第一個篩選會提及單一資料行 ( TimeGenerated ),而第二個篩選則會參考兩個數據行 ( Resource 和 ResourceGroup )。

摘要資料

Summarize 是Kusto 查詢語言中最重要的表格式運算子之一,但它也是較複雜的運算子之一,可瞭解您是否是一般查詢語言的新手。 summarize的工作是在資料表中接受,並輸出由 一或多個資料行匯總的新資料表

summarize 語句的結構

語句的基本結構 summarize 如下所示:

| summarize <aggregation> by <column>

例如,下列會傳回 Perf 資料表中 每個 CounterName 值的記錄計數:

Perf
| summarize count() by CounterName

Screenshot of results of summarize operator with count aggregation.

因為 的輸出 summarize 是新的資料表,因此語句中 summarize 未明確指定的任何資料行都不會 傳遞至管線。 若要說明此概念,請考慮下列範例:

Perf
| project ObjectName, CounterValue, CounterName
| summarize count() by CounterName
| sort by ObjectName asc

在第二行上,我們會指定我們只關心 ObjectName、CounterValue CounterName 資料行 然後摘要說明要依 CounterName 取得記錄計數,最後,我們會嘗試根據 ObjectName 資料行以遞增順序排序資料。 不幸的是,此查詢將會失敗,並出現錯誤(表示 ObjectName 未知),因為當我們摘要時,我們只會在新 資料表中包含 Count CounterName 資料行。 若要避免此錯誤,我們只需將 ObjectName 新增 至步驟 summarize 結尾,如下所示:

Perf
| project ObjectName, CounterValue , CounterName
| summarize count() by CounterName, ObjectName
| sort by ObjectName asc

讀取您頭部中行的方式 summarize 是:「依 CounterName 摘要記錄計數 ,以及依 ObjectName 分組」。 您可以繼續將以逗號分隔的資料行加入語句結尾 summarize

Screenshot of results of summarize operator with two arguments.

在上一個範例的基礎上,如果我們想要同時匯總多個資料行,我們可以藉由將匯總新增至 summarize 運算子來達成此目的,並以逗號分隔。 在下列範例中,我們不僅會取得所有記錄的計數,而且會取得所有記錄的 CounterValue 資料行值總和(符合查詢中的任何篩選準則):

Perf
| project ObjectName, CounterValue , CounterName
| summarize count(), sum(CounterValue) by CounterName, ObjectName
| sort by ObjectName asc

Screenshot of results of summarize operator with multiple aggregations.

重新命名匯總資料行

這似乎是談論這些匯總資料行之資料行名稱的好時機。 在本節 開始時,我們表示 summarize 運算子會採用資料表並產生新的資料表,而且只有您在 語句中指定的 summarize 資料行會繼續向下管線。 因此,如果您要執行上述範例,則匯總的結果資料行會 count_ sum_CounterValue

Kusto 引擎會自動建立資料行名稱,而不需要我們明確,但通常,您會發現您偏好新資料行具有更易記的名稱。 您可以藉由指定新的名稱以及 = 匯總,輕鬆地在 語句中 summarize 重新命名資料行,如下所示:

Perf
| project ObjectName, CounterValue , CounterName
| summarize Count = count(), CounterSum = sum(CounterValue) by CounterName, ObjectName
| sort by ObjectName asc

現在,我們的摘要資料行將會命名為 Count CounterSum

Screenshot of friendly column names for aggregations.

操作員比我們在這裡所涵蓋的要多 summarize 得多,但您應該投資時間來瞭解它,因為它是您計畫對 Microsoft Sentinel 資料執行之任何資料分析的關鍵元件。

匯總參考

有許多彙總函式,但最常使用的其中一些是 sum()count()avg() 。 以下是部分清單(請參閱 完整清單 ):

彙總函數

函式 描述
arg_max() 當引數最大化時,傳回一或多個運算式
arg_min() 當引數最小化時,傳回一或多個運算式
avg() 傳回整個群組的平均值
buildschema() 傳回允許動態輸入所有值的最小架構
count() 傳回群組的計數
countif() 傳回具有群組述詞的計數
dcount() 傳回群組元素的近似相異計數
make_bag() 傳回群組內動態值的屬性包
make_list() 傳回群組內所有值的清單
make_set() 傳回群組內的一組相異值
max() 傳回整個群組的最大值
min() 傳回整個群組的最小值
percentiles() 傳回群組的百分位數近似值
stdev() 傳回整個群組的標準差
sum() 傳回群組內專案的總和
take_any() 傳回群組的隨機非空白值
variance() 傳回整個群組的變異數

選取:新增和移除資料行

當您開始使用查詢時,您可能會發現您擁有的資訊比您主題所需的資訊多(也就是資料表中的資料行太多)。 或者,您可能需要比您擁有的更多資訊(也就是說,您需要新增包含其他資料行分析結果的資料行)。 讓我們看看一些用於資料行操作的索引鍵運算子。

Project 和 project-away

Project 大致相當於許多語言的 select 語句。 它可讓您選擇要保留的資料行。 傳回的資料行順序會符合您在語句中 project 列出之資料行的順序,如下列範例所示:

Perf
| project ObjectName, CounterValue, CounterName

Screenshot of results of project operator.

如您所想像,當您使用非常廣泛的資料集時,您可能會有許多想要保留的資料行,並以名稱指定這些資料行需要大量輸入。 在這些情況下,您會有 project-away ,可讓您指定要移除的資料行,而不是要保留哪些資料行,如下所示:

Perf
| project-away MG, _ResourceId, Type

提示

在查詢的兩個位置中,一開始和一次又一次地用於 project 查詢中,這非常有用。 在查詢早期使用 project ,可藉由去除您不需要傳遞管線的大量資料,來協助改善效能。 在結尾再次使用它可讓您擺脫先前步驟中可能已建立的任何資料行,而且不需要在最終輸出中。

擴充

Extend 是用來建立新的匯出資料行。 當您想要對現有資料行執行計算,並查看每個資料列的輸出時,這非常有用。 讓我們看看一個簡單的範例,其中我們計算名為 Kbytes 的新資料行,我們可以藉由將 MB 值 乘以 1,024 來計算。

Usage
| where QuantityUnit == 'MBytes'
| extend KBytes = Quantity * 1024
| project ResourceUri, MBytes=Quantity, KBytes

在 語句的最後一行 project 上,我們已將 Quantity 資料行重新命名為 Mbytes ,因此我們可以輕鬆地判斷哪一個量值單位與每個資料行有關。

Screenshot of results of extend operator.

值得注意的是, extend 也適用于已經計算的資料行。 例如,我們可以新增一個名為 Bytes 的資料行,此資料行 是從 Kbytes 計算而來:

Usage
| where QuantityUnit == 'MBytes'
| extend KBytes = Quantity * 1024
| extend Bytes = KBytes * 1024
| project ResourceUri, MBytes=Quantity, KBytes, Bytes

Screenshot of results of two extend operators.

聯結資料表

您在 Microsoft Sentinel 中的大部分工作都可以使用單一記錄類型來執行,但有時候您會想要將資料相互關聯或針對另一組資料執行查閱。 和大多數查詢語言一樣,Kusto 查詢語言提供一些運算子,用來執行各種類型的聯結。 在本節中,我們將探討最常使用的運算子 unionjoin

Union

等位 只會採用兩個或多個資料表,並傳回所有資料列。 例如:

OfficeActivity
| union SecurityEvent

這會從 OfficeActivity SecurityEvent 資料表傳回所有資料列。 Union 提供一些參數,可用來調整等位的行為。 其中兩個最有用的是 搭配source kind

OfficeActivity
| union withsource = SourceTable kind = inner SecurityEvent

withsource 參數可讓您指定新資料行的名稱,該資料行在指定資料列中的值將會是資料列的來來源資料表名稱。 在上述範例中,我們將 SourceTable 命名為數據行,並根據資料列而定,此值會是 OfficeActivity SecurityEvent

我們指定的另一個參數是 kind ,其有兩個選項: 內部 外部 。 在上述範例中,我們指定 了內部 ,這表示聯集期間將保留的唯一資料行是存在於這兩個數據表中的資料行。 或者,如果我們已指定 外部 值(也就是預設值),則會傳回這兩個數據表中的所有資料行。

聯結

聯結 的運作方式類似于 union ,除了聯結資料表來建立新的資料表之外,我們會聯 結資料列 來建立新的資料表。 和大多數資料庫語言一樣,您可以執行的聯結類型有很多種。 的 join 一般語法為:

T1
| join kind = <join type>
(
               T2
) on $left.<T1Column> == $right.<T2Column>

join 運算子之後,我們會指定 我們想要執行的聯結種類 ,後面接著左括弧。 在括弧內,指定您要聯結的資料表,以及您想要加入之資料表 的任何其他查詢語句。 在右括弧之後,我們使用 on 關鍵字後面接著左方 ( $left。 <columnName > 關鍵字) 和右側 ( $right。 <columnName > ) 以 == 運算子分隔的資料行。 以下是內部聯結 範例:

OfficeActivity
| where TimeGenerated >= ago(1d)
    and LogonUserSid != ''
| join kind = inner (
    SecurityEvent
    | where TimeGenerated >= ago(1d)
        and SubjectUserSid != ''
) on $left.LogonUserSid == $right.SubjectUserSid

注意

如果這兩個數據表對執行聯結的資料行具有相同的名稱,則不需要使用 $left $right ;相反地,您可以只指定資料行名稱。 不過,使用 $left $right 更為明確,而且通常被視為最佳做法。

如需參考,下表顯示可用的聯結類型清單。

聯結類型

聯結類型 描述
inner 針對這兩個數據表中相符資料列的每個組合,各傳回單一。
innerunique 從左資料表傳回具有右資料表相符專案之連結欄位中相異值的資料列。
這是預設未指定的聯結類型。
leftsemi 傳回左資料表中符合右資料表的所有記錄。
只會傳回左資料表中的資料行。
rightsemi 從右資料表傳回在左資料表中符合的所有記錄。
只會傳回來自右資料表的資料行。
leftanti/
leftantisemi
從左資料表傳回在右資料表中沒有相符專案的所有記錄。
只會傳回左資料表中的資料行。
rightanti/
rightantisemi
從右資料表傳回在左資料表中沒有相符專案的所有記錄。
只會傳回來自右資料表的資料行。
leftouter 傳回左資料表中的所有記錄。 對於右資料表中沒有相符的記錄,儲存格值會是 Null。
rightouter 從右資料表傳回所有記錄。 對於左資料表中沒有相符的記錄,儲存格值會是 Null。
fullouter 傳回左右資料表的所有記錄,比對或否。
不相符的值將會是 Null。

提示

最好 在左邊有最小的資料表。 在某些情況下,遵循此規則可以為您提供巨大的效能優勢,視您執行的聯結類型和資料表大小而定。

評估

您可能會記得,回到 第一個範例 中,我們在其中一行上看到了 評估 運算子。 evaluate運算子較先前所接觸的運算子較不常使用。 不過,知道操作員的運作 evaluate 方式非常值得您的時間。 再一次,以下是第一個查詢,您會在第二行看到 evaluate 此查詢。

SigninLogs
| evaluate bag_unpack(LocationDetails)
| where RiskLevelDuringSignIn == 'none'
   and TimeGenerated >= ago(7d)
| summarize Count = count() by city
| sort by Count desc
| take 5

此運算子可讓您叫用可用的外掛程式(基本上是內建函式)。 其中許多外掛程式著重于資料科學,例如 autocluster diffpatterns sequence_detect ,可讓您執行進階分析和探索統計異常和極端值。

上述範例中使用的外掛程式稱為 「bag_unpack 」,它可讓您輕鬆地取得動態資料的區塊,並將其轉換成資料行。 請記住, 動態資料 是類似 JSON 的資料類型,如下列範例所示:

{
"countryOrRegion":"US",
"geoCoordinates": {
"longitude":-122.12094116210936,
"latitude":47.68050003051758
},
"state":"Washington",
"city":"Redmond"
}

在此情況下,我們想要依城市摘要資料,但 city 會包含在 LocationDetails 資料行內 作為屬性。 若要在查詢中使用 city 屬性,我們必須先使用 bag_unpack 將其轉換成資料行。

回到原始管線步驟,我們看到了:

Get Data | Filter | Summarize | Sort | Select

既然我們已經考慮 evaluate 運算子,我們可以看到它代表管線中的新階段,現在看起來像這樣:

Get Data | Parse | Filter | Summarize | Sort | Select

還有其他許多運算子和函式範例可用來將資料來源剖析為更容易閱讀和操作的格式。 您可以在完整檔和 活頁簿 中 瞭解它們及其其餘Kusto 查詢語言。

let 陳述式

既然我們已經涵蓋許多主要運算子和資料類型,讓我們來總結 let 語句 ,這是讓您的查詢更容易讀取、編輯和維護的絕佳方式。

可讓您 建立和設定變數,或將名稱指派給運算式。 此運算式可以是單一值,但也可能是整個查詢。 以下是簡單的範例:

let aWeekAgo = ago(7d);
SigninLogs
| where TimeGenerated >= aWeekAgo

在這裡,我們指定了 aWeekAgo 的名稱 ,並將它設定為等於時間範圍 函式的 輸出,其會 傳回 datetime 值。 然後, 我們會以分號終止 let 語句。 現在我們有一 個名為 aWeekAgo 的新變數,可在查詢中的任何位置使用。

如我們剛才所述,您可以使用 let 語句來取得整個查詢,並指定結果名稱。 由於查詢結果是表格式運算式,可用來做為查詢的輸入,因此您可以將這個具名結果視為資料表,以便執行另一個查詢。 以下是先前範例的稍微修改:

let aWeekAgo = ago(7d);
let getSignins = SigninLogs
| where TimeGenerated >= aWeekAgo;
getSignins

在此案例中,我們建立了第二 個 let 語句,其中會將整個查詢包裝成名為 getSignins 的新變數。 就像之前一樣,我們會以分號終止第二 個 let 語句。 然後,我們會在最後一行上呼叫 變數,以執行查詢。 請注意,我們能夠在第二 個 let 語句中使用 aWeekAgo 。 這是因為我們在上一行指定了它;如果我們要交換 let 語句, 讓 getSignins 先來, 我們會收到錯誤。

現在,我們可以使用 getSignins 作為另一個查詢的基礎(在同一個視窗中):

let aWeekAgo = ago(7d);
let getSignins = SigninLogs
| where TimeGenerated >= aWeekAgo;
getSignins
| where level >= 3
| project IPAddress, UserDisplayName, Level

Let 語句可讓您更強大且彈性地協助組織查詢。 讓我們 定義純量和表格式值,以及建立使用者定義的函式。 當您組織更複雜的查詢時,它們確實會派上用場,這些查詢可能會執行多個聯結。

下一步

雖然本文幾乎沒有劃過表面,但您現在已有必要的基礎,我們已涵蓋您將最常使用以在 Microsoft Sentinel 中完成工作的元件。

適用于 Microsoft Sentinel 活頁簿的進階 KQL

利用 Microsoft Sentinel 本身的Kusto 查詢語言活頁簿 - Microsoft Sentinel 活頁簿的進階 KQL。 它提供您在日常安全性作業期間可能遇到的許多情況的逐步說明和範例,同時也會指出許多現成的現成分析規則、活頁簿、搜捕規則,以及更多使用 Kusto 查詢的元素範例。 從 Microsoft Sentinel 中的 [ 活頁簿] 刀鋒視窗啟動此活頁簿。

進階 KQL Framework 活頁簿 - 讓您成為 KQL 精明 的優秀部落格文章,示範如何使用此活頁簿。

更多資源

請參閱 此學習、訓練和技能資源 集合,以擴大和加深您對Kusto 查詢語言的知識。