Real-Time Intelligence · Microsoft Fabric 2026

KQL Tutorial for Microsoft Fabric: Eventhouse & Real-Time Intelligence

KQL (Kusto Query Language) is the query language for every Fabric Eventhouse. If you use Eventstream, build real-time dashboards, or work with IoT and log data in Fabric, KQL is what you write to get answers. This guide covers the pipe syntax from scratch, every operator you’ll use in production, time series analysis, anomaly detection, materialized views, update policies, and 8 real-world query patterns you can use immediately.

What is KQL in Microsoft Fabric?

KQL (Kusto Query Language) is the query language for Microsoft Fabric Eventhouse and KQL Databases. It uses a pipe-based syntax where data flows through a sequence of operators: TableName | where condition | summarize aggregation. KQL is optimized for time-series data, log analytics, telemetry, and high-volume streaming data. In Fabric, KQL queries data ingested from Eventstream sources — Event Hubs, Kafka, IoT Hub, MQTT — and is also tested on the DP-700 exam under Domain 2 (Ingest and Transform Data). (per Microsoft Learn — KQL Overview)

📅 Last verified: June 2026 Read time: ~16 min ✍️ A.J., Data Engineering Researcher 🔗 Source: Microsoft Learn KQL

The Eventhouse — Where KQL Lives in Microsoft Fabric

Before writing a single KQL query, you need to understand what you are querying. In Microsoft Fabric, Eventhouse is the analytical engine for the Real-Time Intelligence workload. It is the equivalent of a database server — but designed specifically for time-series and event-based data at high ingestion rates.

Each Eventhouse contains one or more KQL Databases. Each KQL Database contains tables, materialized views, stored functions, update policies, ingestion mappings, and OneLake shortcuts. When you create an Eventhouse in Fabric, it typically auto-creates a KQL Database with the same name — your starting point for writing queries.

Per Microsoft Learn, Eventhouse is designed for any scenario that includes event-based data: telemetry and log data, time series and IoT data, security and compliance logs, and financial records.

What Makes Eventhouse Different from a SQL Database

  • Append-only tables: KQL tables receive new records continuously. Old data is rarely updated. This design supports massive ingestion rates efficiently.
  • Sub-second queries at scale: KQL queries across billions of rows return results in seconds. The engine uses columnar storage, compression, and indexing tuned for time-based filtering.
  • Time-based indexing: Every KQL table has an ingestion time column automatically. Time-based filters like ago(1h) are highly optimized.
  • Auto-refresh materialized views: Pre-computed aggregations update automatically as new data arrives — no manual refresh or pipeline needed.
  • OneLake Availability: Enable at the table or database level to mirror KQL data to OneLake in Delta-Parquet format — making it queryable by Spark, Warehouse, and Power BI Direct Lake.
📌

Eventhouse + Eventstream — The Complete RTI Stack

The standard Fabric RTI pattern: Eventstream ingests streaming data from sources (Event Hubs, Kafka, IoT Hub, MQTT) and routes events to an Eventhouse KQL Database destination. From there, KQL queries the landed data. Data Activator monitors the stream for conditions and fires alerts. Power BI connects to the Eventhouse for real-time dashboards. All four components work together — Eventstream handles ingestion, Eventhouse handles storage and querying, Data Activator handles alerting, Power BI handles visualization.

KQL Pipe Syntax — How Every Query Is Structured

KQL uses a pipe-based syntax. Every query starts with a table name and then pipes the result through a sequence of operators. Each operator receives the output of the previous one and transforms it. You read a KQL query left-to-right (or top-to-bottom) like a recipe: start with the data, filter it, reshape it, aggregate it, render it.

Basic KQL query structure
// TableName is always first — no FROM keyword needed // Each | operator receives the output of the previous oneSensorReadings // start: all rows in the table | where Timestamp > ago(1h) // filter: last hour only | where Temperature > 75 // filter: high temperature readings | summarize AvgTemp = avg(Temperature) // aggregate: average per group by bin(Timestamp, 5m), DeviceId // group by 5-minute windows and device | order by Timestamp desc // sort: newest first | take 100 // limit: top 100 rows

Key Syntax Rules

  • Table name first, no FROM: Unlike SQL, you don’t write FROM TableName SELECT. The table name starts the query.
  • Pipe separates operators: The | character passes the result of one operator to the next.
  • Case-sensitive identifiers: Column names and table names are case-sensitive. Temperature and temperature are different columns.
  • Comments: Single-line comments use //. Block comments use /* */.
  • let statements: Define variables or subqueries with let at the top of the query. Think of them as CTEs in SQL.
  • String literals: Use single quotes 'value' or double quotes "value".
let statements — variables and subqueries
// let defines a variable or subquery — equivalent to SQL CTE let threshold = 80.0; let start_time = ago(24h);SensorReadings | where Timestamp > start_time | where Temperature > threshold | summarize AlertCount = count() by DeviceId | order by AlertCount desc

KQL vs SQL — Side-by-Side Comparison for Fabric Engineers

If you already know SQL, the fastest way to understand KQL is to see them side by side. The mental model shift: in SQL you declare the structure of the result upfront. In KQL you describe the transformations the data goes through, step by step.

OperationSQLKQL
Select all rowsSELECT * FROM SensorsSensors
Filter rowsSELECT * FROM Sensors WHERE Temp > 80Sensors | where Temp > 80
Select columnsSELECT DeviceId, Temp FROM SensorsSensors | project DeviceId, Temp
Add a columnSELECT *, Temp * 1.8 + 32 AS TempF FROM SensorsSensors | extend TempF = Temp * 1.8 + 32
Count rowsSELECT COUNT(*) FROM SensorsSensors | count
Group and aggregateSELECT DeviceId, AVG(Temp) FROM Sensors GROUP BY DeviceIdSensors | summarize AvgTemp = avg(Temp) by DeviceId
Sort resultsORDER BY Temp DESC| order by Temp desc
Limit rowsTOP 10 / LIMIT 10| take 10
Filter last 1 hourWHERE Timestamp > DATEADD(HOUR,-1,GETDATE())| where Timestamp > ago(1h)
Time bucketsDATEPART(MINUTE, Timestamp)/5*5 (awkward)| summarize … by bin(Timestamp, 5m)
Like / containsWHERE Message LIKE ‘%error%’| where Message contains “error”
Starts withWHERE DeviceId LIKE ‘TEMP%’| where DeviceId startswith “TEMP”
Distinct countCOUNT(DISTINCT DeviceId)dcount(DeviceId) in summarize
Inner joinJOIN TableB ON a.Key = b.Key| join kind=inner TableB on Key

Performance Tip — has vs contains for String Filtering

In KQL, has is significantly faster than contains for string filtering. has performs a whole-term search using an inverted index. contains performs a substring search that scans every row. Use has "error" when searching for a whole word. Use contains "err" only when you need partial string matching and there is no alternative. This performance difference is critical at billion-row scale.

Core KQL Operators — The Complete Reference for Fabric

Filter

where

Filters rows matching a condition. Supports: comparison operators, string operators (has, contains, startswith, matches regex), boolean operators (and, or, not), and in lists.

Transform

project

Selects specific columns, renames them, or creates new calculated columns. Drops all other columns — think SELECT with an explicit column list. Use project-away to drop specific columns and keep the rest.

Transform

extend

Adds new calculated columns without dropping existing ones. The KQL equivalent of SQL computed columns or SELECT *, new_col. Use for unit conversions, derived values, and string parsing.

Aggregate

summarize

Groups rows and computes aggregations. Equivalent to SQL GROUP BY. Aggregation functions: count(), sum(), avg(), min(), max(), dcount(), percentile(), make_list(), make_set(), arg_max(), arg_min().

Time

bin

Rounds values down to the nearest multiple — used in summarize by bin(Timestamp, 5m) to create time buckets. Essential for time series aggregations. Works with timespan values: 1m, 5m, 1h, 1d.

Time

ago

Returns a datetime relative to now. ago(1h) = one hour ago. ago(7d) = seven days ago. Used almost universally in real-time queries: | where Timestamp > ago(1h). Combine with between for time range queries.

Join

join

Combines rows from two tables on a matching key. Join kinds: inner, leftouter, rightouter, fullouter, leftsemi, leftanti. For dimension enrichment, use lookup instead — it is optimized for enriching a large stream with a small dimension table.

Render

render

Generates an inline visualization in the KQL queryset. Useful for exploration: | render timechart, | render barchart, | render piechart. Not used in production queries sent to Power BI or Data Activator — for exploration in the Fabric queryset only.

String Operators — Choosing the Right One

OperatorWhat It DoesCase-Sensitive?Performance
hasWhole-word term matchNo (has_cs for yes)Fastest — uses inverted index
containsSubstring match anywhereNo (contains_cs for yes)Slow — full scan
startswithString starts with valueNo (startswith_cs for yes)Fast — prefix index
endswithString ends with valueNoMedium
matches regexRegular expression matchYesSlowest — use as last resort
inValue in a listNo (in~ for case-insensitive)Fast for small lists

Time Series Analysis — KQL’s Most Powerful Capability

Time series analysis is where KQL dramatically outperforms SQL. Built-in functions for binning, sliding windows, anomaly detection, and forecasting are native to the language — in SQL these require multiple CTEs, window functions, and custom implementations.

Time-Based Filtering

Common time filters in Fabric Eventhouse
// Last N time units SensorReadings | where Timestamp > ago(1h) // last hour SensorReadings | where Timestamp > ago(7d) // last 7 days// Specific range SensorReadings | where Timestamp between (datetime(2026-06-01) .. datetime(2026-06-07))// Today only SensorReadings | where Timestamp >= startofday(now())// This week SensorReadings | where Timestamp >= startofweek(now())

Time Series Aggregation with bin()

5-minute averages per device — standard RTI pattern
// Average temperature per device in 5-minute windows — last 24 hours SensorReadings | where Timestamp > ago(24h) | summarize AvgTemp = avg(Temperature), MaxTemp = max(Temperature), ReadingCnt = count() by bin(Timestamp, 5m), DeviceId | order by DeviceId asc, Timestamp asc

make-series — Time Series Arrays for Advanced Analysis

The make-series operator creates a time series array from a set of values — one array per group, one element per time step. This is the input format for KQL’s built-in ML functions: anomaly detection, forecasting, and trend decomposition.

make-series + anomaly detection
// Create time series arrays then detect anomalies — Fabric Eventhouse SensorReadings | where Timestamp > ago(7d) | make-series AvgTemp = avg(Temperature) on Timestamp from ago(7d) to now() step 1h by DeviceId | extend Anomalies = series_decompose_anomalies(AvgTemp), Baseline = series_decompose(AvgTemp) | mv-expand Timestamp to typeof(datetime), AvgTemp to typeof(real), Anomalies to typeof(int) | where Anomalies != 0 | project Timestamp, DeviceId, AvgTemp, Anomalies
📌

series_decompose_anomalies — How It Works

This function decomposes a time series into trend, seasonality, and residual components, then identifies points where the residual exceeds a threshold (default 1.5 standard deviations). It returns a score per time step: 1 (high anomaly), -1 (low anomaly), 0 (normal). No training data required — it learns the pattern from the series itself. Use it in Eventstream-fed Eventhouse tables for automated IoT anomaly detection without a separate ML pipeline.

Forecasting with series_decompose_forecast()

Forecast next 24 hours based on last 7 days
SensorReadings | where Timestamp > ago(7d) | make-series AvgTemp = avg(Temperature) on Timestamp from ago(7d) to now() + 24h step 1h by DeviceId | extend Forecast = series_decompose_forecast(AvgTemp, 24) | mv-expand Timestamp to typeof(datetime), AvgTemp to typeof(real), Forecast to typeof(real) | project Timestamp, DeviceId, AvgTemp, Forecast

Joins and Lookups — Combining Tables in KQL

KQL supports all standard join types but the syntax differs from SQL. The key practical difference: the left table in a KQL join should be the larger table (your event stream), and the right table should be the smaller table (your dimension/enrichment data). This is the opposite of some SQL convention instincts.

Standard inner join — enrich events with device metadata
// Enrich sensor readings with device metadata // Left: large event stream | Right: small dimension table SensorReadings | where Timestamp > ago(1h) | join kind=inner ( DeviceMetadata | project DeviceId, Location, DeviceType, Owner ) on DeviceId | project Timestamp, DeviceId, Temperature, Location, DeviceType
lookup — optimized for stream + small dimension (preferred over join for enrichment)
// lookup is broadcast-optimized for large stream + small dimension // More efficient than join for standard enrichment patterns SensorReadings | where Timestamp > ago(1h) | lookup DeviceMetadata on DeviceId | project Timestamp, DeviceId, Temperature, Location, Owner
Join KindWhat It ReturnsSQL Equivalent
innerRows that match in both tablesINNER JOIN
leftouterAll left rows, nulls for right non-matchesLEFT OUTER JOIN
rightouterAll right rows, nulls for left non-matchesRIGHT OUTER JOIN
fullouterAll rows from both tablesFULL OUTER JOIN
leftsemiLeft rows that have a match in right (only left columns)WHERE EXISTS
leftantiLeft rows that have NO match in rightWHERE NOT EXISTS
lookupBroadcast-optimized enrichment — large left + small rightOptimized LEFT JOIN

Materialized Views, Update Policies & Stored Functions

Materialized Views — Pre-Computed Aggregations That Auto-Update

Per Microsoft Learn, materialized views expose an aggregation query over a source table and automatically update as new data arrives. They consist of two parts: a materialized part (pre-computed results from already-processed data) and a delta (new data since the last background update). When you query a materialized view, the system combines both parts to return always-current results.

Materialized views encapsulate a single summarize statement. They are the Gold layer of a KQL-native Medallion Architecture — Silver is the raw ingested table, Gold is the materialized view with the business aggregation pre-computed.

Create a materialized view — hourly averages per device
.create materialized-view with (backfill=true) HourlyDeviceMetrics on table SensorReadings { SensorReadings | summarize AvgTemp = avg(Temperature), MaxTemp = max(Temperature), MinTemp = min(Temperature), Readings = count() by bin(Timestamp, 1h), DeviceId }

Querying a materialized view is identical to querying a table:

Query the materialized view — instant results, no recalculation
// Returns pre-computed hourly aggregations — no recalculation from raw data HourlyDeviceMetrics | where Timestamp > ago(7d) | where DeviceId == “TEMP-A4291” | order by Timestamp asc | render timechart

backfill=true — Populate from Historical Data

When you create a materialized view with backfill=true, Fabric processes existing historical data in the source table and pre-computes results for all past time periods — not just future ingestion. Without backfill, the view starts empty and builds from the next ingested event forward. Use backfill when you need historical coverage from day one. Be aware that backfill can take time on large tables.

Update Policies — Transform Data at Ingestion Time

An update policy runs a KQL function automatically every time new data is ingested into the source table. The function’s output is appended to a target table. This is the KQL equivalent of a Silver transformation — raw events land in the Bronze table, the update policy transforms them and writes normalized rows to the Silver table, all within the Eventhouse without any external pipeline.

Update policy — parse JSON IoT events at ingestion time
// Step 1: Create the Silver table (transformed target) .create table SensorReadingsParsed ( Timestamp: datetime, DeviceId: string, Temperature:real, Humidity: real, Location: string )// Step 2: Create the transformation function .create function ParseSensorEvent() { SensorReadingsRaw | extend ParsedPayload = parse_json(Payload) | project Timestamp = todatetime(ParsedPayload.ts), DeviceId = tostring(ParsedPayload.device_id), Temperature = todouble(ParsedPayload.temp_c), Humidity = todouble(ParsedPayload.humidity_pct), Location = tostring(ParsedPayload.loc) }// Step 3: Attach the update policy to the source table .alter table SensorReadingsRaw policy update @'[{“IsEnabled”: true, “Source”: “SensorReadingsRaw”, “Query”: “ParseSensorEvent()”, “IsTransactional”: true, “PropagateIngestionProperties”: true}]’

Stored Functions — Reusable KQL Queries

Stored functions in Eventhouse are named, parameterized KQL expressions stored in the KQL Database. Call them like a table reference or with parameters. Useful for standard query patterns that your team runs repeatedly — device health checks, error rate calculations, and SLA evaluations.

Create and call a stored function
// Create a stored function with a parameter .create function GetDeviceAlerts(device_id: string, lookback: timespan) { SensorReadings | where DeviceId == device_id | where Timestamp > ago(lookback) | where Temperature > 80 or Temperature < 10 | project Timestamp, DeviceId, Temperature | order by Timestamp desc }// Call the function GetDeviceAlerts(“TEMP-A4291”, 24h)

8 Real-World KQL Query Patterns for Fabric Eventhouse

Pattern 1 — Latest Reading Per Device

Get the most recent event for each device — the “current state” query. Common for IoT dashboards showing live sensor values.

Pattern 2 — Error Rate Over Time

Calculate the percentage of error events per time bucket. Common for application log monitoring and SLA dashboards.

Pattern 3 — Top N by Metric

Find the top N entities by a metric in a time window. Common for identifying highest-consuming devices, top error sources, and peak users.

Pattern 4 — Week-Over-Week Comparison

Compare current week values against the same period last week. Common for business reporting and trend detection.

Pattern 1 — Latest reading per device (arg_max)
// Get the most recent temperature reading for each device // arg_max returns the row with the maximum Timestamp per DeviceId SensorReadings | where Timestamp > ago(1h) | summarize arg_max(Timestamp, *) by DeviceId | project DeviceId, Timestamp, Temperature, Location | order by Temperature desc
Pattern 2 — Error rate per hour (calculated percentage)
// Error rate as percentage of total events per hour AppLogs | where Timestamp > ago(24h) | summarize TotalEvents = count(), ErrorEvents = countif(Level == “error”) by bin(Timestamp, 1h) | extend ErrorRate = round(100.0 * ErrorEvents / TotalEvents, 2) | order by Timestamp desc
Pattern 3 — Top 10 devices by max temperature in last 24h
SensorReadings | where Timestamp > ago(24h) | summarize MaxTemp = max(Temperature) by DeviceId | top 10 by MaxTemp desc | join kind=leftouter ( DeviceMetadata | project DeviceId, Location ) on DeviceId | project DeviceId, Location, MaxTemp
Pattern 4 — Week-over-week comparison
// Compare this week vs last week — same hour of day let this_week = SensorReadings | where Timestamp > ago(7d) | summarize ThisWeek = avg(Temperature) by bin(Timestamp, 1h), DeviceId;let last_week = SensorReadings | where Timestamp between (ago(14d) .. ago(7d)) | summarize LastWeek = avg(Temperature) by bin(Timestamp + 7d, 1h), DeviceId;this_week | join kind=inner last_week on Timestamp, DeviceId | extend WoW_Delta = round(ThisWeek – LastWeek, 2) | order by WoW_Delta desc
Pattern 5 — Session analysis (user activity windows)
// Identify sessions: events within 30 minutes of each other are the same session // session_count assigns a new session when gap > 30 minutes UserEvents | where Timestamp > ago(7d) | sort by UserId asc, Timestamp asc | extend PrevTimestamp = prev(Timestamp, 1) | extend IsNewSession = iif( UserId != prev(UserId, 1) or Timestamp – PrevTimestamp > 30m, 1, 0) | extend SessionId = row_cumsum(IsNewSession) | summarize SessionStart = min(Timestamp), SessionEnd = max(Timestamp), EventCount = count(), SessionMinutes = datetime_diff(‘minute’, max(Timestamp), min(Timestamp)) by UserId, SessionId | order by SessionMinutes desc
Pattern 6 — Spike detection (value exceeds rolling average by threshold)
// Detect spikes: current value > 2x the rolling 1-hour average SensorReadings | where Timestamp > ago(24h) | summarize AvgTemp = avg(Temperature) by bin(Timestamp, 5m), DeviceId | order by DeviceId asc, Timestamp asc | extend RollingAvg = series_stats_dynamic(make_list(AvgTemp)) | where AvgTemp > 2 * prev(AvgTemp, 12, 0.0) // 12 = 60min / 5min window | project Timestamp, DeviceId, AvgTemp
Pattern 7 — Distributed tracing (correlate events by trace ID)
// Find all events in a distributed trace and calculate span durations TracingEvents | where Timestamp > ago(1h) | where TraceId == “abc-123-def” | order by Timestamp asc | extend SpanDuration = next(Timestamp, 1) – Timestamp | project Timestamp, ServiceName, Operation, SpanDuration, Status
Pattern 8 — Funnel analysis (conversion through steps)
// Count users completing each step of a funnel let step1 = UserEvents | where EventType == “page_view” | summarize dcount(UserId); let step2 = UserEvents | where EventType == “add_to_cart” | summarize dcount(UserId); let step3 = UserEvents | where EventType == “checkout” | summarize dcount(UserId); let step4 = UserEvents | where EventType == “purchase” | summarize dcount(UserId);union (step1 | extend Step = “1. Page View”), (step2 | extend Step = “2. Add to Cart”), (step3 | extend Step = “3. Checkout”), (step4 | extend Step = “4. Purchase”) | project Step, Users = Column1 | order by Step asc

OneLake Availability — Bridge Eventhouse Data to the Rest of Fabric

Per Microsoft Learn: OneLake Availability can be enabled at the database or table level in Eventhouse. When enabled, it mirrors KQL table data to OneLake in Delta-Parquet format — making it queryable by other Fabric engines without copying or duplicating data.

What OneLake Availability Enables

  • Power BI Direct Lake: Connect a semantic model directly to Delta files mirrored from Eventhouse — no import refresh, no DirectQuery overhead, always-current data
  • Fabric Warehouse: Run T-SQL queries over Eventhouse data via an OneLake shortcut pointing to the mirrored Delta files
  • Fabric Lakehouse: Join Eventhouse data with Lakehouse tables in a Spark Notebook — real-time events + historical batch data in a single PySpark query
  • Medallion in Eventhouse: Materialized views in Eventhouse with OneLake Availability enabled create a KQL-native Gold layer that Power BI can read via Direct Lake

Enable OneLake Availability

In the Fabric portal, open your Eventhouse → navigate to the KQL Database → open the database settings → enable OneLake Availability at the database level (covers all tables) or per table. After enabling, the data is mirrored to a Delta Lake location in OneLake. The location appears in the database properties and can be referenced as a Lakehouse shortcut.

⚠️

OneLake Availability Adds Storage Cost

Enabling OneLake Availability creates a Delta-Parquet copy of your KQL data in OneLake. This doubles the storage footprint for that table — the original Eventhouse column store plus the Delta-Parquet copy in OneLake. For large tables (hundreds of GB+), evaluate whether the cross-engine access benefit justifies the additional storage cost. OneLake storage is billed at $0.023/GB/month.

The combination of Eventstream → Eventhouse → OneLake Availability → Direct Lake creates a complete real-time analytics pipeline where data ingested from IoT sensors appears in Power BI reports within seconds — without a scheduled refresh, without data duplication at the semantic model layer, and without any ETL pipeline between the event and the dashboard. This is the architecture that replaces traditional streaming → data lake → ETL → reporting pipelines for time-series workloads.

KQL and the DP-700 Exam — What You Need to Know

KQL is tested on the DP-700 exam under Domain 2: Ingest and Transform Data (30–35%). The exam does not expect advanced KQL mastery — it tests whether you can use KQL for practical Eventhouse scenarios. These are the specific skills tested:

DP-700 SkillWhat It Means in PracticeKey KQL Operator
Select, filter, and aggregate data using KQLWrite basic KQL queries: where, project, summarize, order by, takewhere, summarize, project
Discover data using Real-Time HubNavigate the Real-Time Hub to find Eventstream and Eventhouse itemsN/A — UI navigation
Ingest or access data as neededConfigure Eventstream → Eventhouse KQL Database destinationN/A — portal configuration
Implement OneLake integration for EventhouseEnable OneLake Availability on KQL Database or tablesN/A — portal configuration
Choose between different data storesKnow when to use Eventhouse (time series, streaming) vs Lakehouse (batch) vs Warehouse (SQL analytics)N/A — architectural decision
📌

DP-700 KQL Exam Focus — What to Prioritize

  • Know the pipe syntax: table | where | summarize | project | order by | take
  • Know ago() and bin() for time-based queries — these appear in almost every RTI exam scenario
  • Know when Eventhouse is the right data store (streaming, time-series, IoT) vs when Lakehouse (batch Delta) or Warehouse (SQL) is correct
  • Know that KQL tables are append-only and ingestion time is automatically tracked
  • Know how to configure Eventstream → Eventhouse as a destination (the portal steps, not the KQL)
  • Materialized views, update policies, and anomaly detection are NOT required for DP-700 — they appear in DP-600 Real-Time Intelligence topics

For the complete DP-700 study plan covering all three domains with a 6-week schedule, see our DP-700 Exam Guide. For interview questions covering Real-Time Intelligence and Eventhouse scenarios, see our Real-Time Intelligence Interview Questions.

FAQ – KQL Tutorial for Microsoft Fabric

What is KQL in Microsoft Fabric?
KQL (Kusto Query Language) is the query language for Microsoft Fabric Eventhouse and KQL Databases. It uses a pipe-based syntax where data flows through a sequence of operators: TableName | where condition | summarize aggregation. KQL is optimized for time-series data, log analytics, telemetry, and high-volume streaming data. In Fabric’s Real-Time Intelligence workload, KQL queries data ingested from Eventstream sources including Event Hubs, Kafka, IoT Hub, and MQTT.
What is the difference between KQL and SQL in Microsoft Fabric?
KQL uses pipe-based syntax (data flows through operators step by step) optimized for time-series and streaming data. SQL uses clause-based syntax (SELECT-FROM-WHERE) optimized for relational queries. In Fabric: use KQL for Eventhouse (Real-Time Intelligence, IoT, log analytics, streaming); use SQL for Fabric Warehouse (analytical SQL, T-SQL star schemas) and Lakehouse SQL analytics endpoint (ad-hoc SQL on Delta tables).
What is an Eventhouse in Microsoft Fabric?
Eventhouse is the analytical engine for Real-Time Intelligence in Microsoft Fabric. It contains KQL Databases that store time-series data ingested from streaming sources. Eventhouse is designed for event-based data: telemetry and log data, time series and IoT data, security and compliance logs, and financial records. It supports continuous high-throughput ingestion, sub-second KQL queries across billions of rows, materialized views, update policies, and OneLake Availability for cross-engine access.
What are materialized views in KQL Eventhouse?
Materialized views in Eventhouse are pre-computed aggregation queries that automatically update as new data arrives. They encapsulate a single summarize statement. They consist of a materialized part (pre-computed results from already-processed data) and a delta (new data since the last background update). When queried, both parts are combined to return always-current results. Materialized views eliminate the need to recalculate aggregations from billions of historical rows on every query — making them essential for real-time dashboards.
What is OneLake Availability in Eventhouse?
OneLake Availability mirrors KQL table data to OneLake in Delta-Parquet format. When enabled at the database or table level, KQL data becomes queryable by Power BI Direct Lake, Fabric Warehouse, Fabric Lakehouse, and Spark Notebooks — without copying or duplicating data. It creates a bridge between the real-time Eventhouse workload and the broader Fabric analytics ecosystem. Enabling OneLake Availability doubles storage footprint (Eventhouse columnar store + Delta-Parquet copy) — evaluate the storage cost for large tables.
Is KQL tested on the DP-700 exam?
Yes. KQL is tested under DP-700 Domain 2 (Ingest and Transform Data). The exam tests basic KQL: where, summarize, project, order by, take, ago(), and bin(). It also tests Eventhouse as a data store choice and Eventstream → Eventhouse configuration. Advanced KQL (materialized views, update policies, anomaly detection) is not required for DP-700 — it appears in DP-600 Real-Time Intelligence topics.

⚠️ Accuracy Disclaimer

All KQL syntax, Eventhouse features, materialized view behavior, OneLake Availability details, and throttling levels are verified against Microsoft Learn KQL Overview, Eventhouse Overview, and Query Data in KQL Database training module as of June 2026. KQL and Eventhouse capabilities update frequently — verify current syntax and feature availability on Microsoft Learn before production implementation. UIG Data Lab is an independent publication, not affiliated with or endorsed by Microsoft Corporation.

AJ
A.J. Data Engineering Researcher & Technical Writer · UIG Data Lab All articles →

A.J. researches and writes about data engineering, analytics architecture, Microsoft Fabric, and modern cloud data platforms. Coverage spans Microsoft Fabric, Power BI, Azure Data Engineering, Databricks, Snowflake, Apache Spark, dbt, Apache Airflow, and modern cloud data infrastructure. The focus is practitioner-level content that helps data professionals understand platform capabilities, evaluate technology decisions, optimize costs, and implement practical solutions using official documentation, product updates, community insights, and industry best practices. His writing covers real decisions from real deployments — not documentation rewrites.

KQL Eventhouse Microsoft Fabric Real-Time Intelligence Time Series Anomaly Detection Materialized Views Eventstream DP-700

Scroll to Top