-
Notifications
You must be signed in to change notification settings - Fork 0
PBI Dataset Health Performance Metrics
Related script:
scripts/Graph Commands/Get-PBIWorkspaceUsageReport.ps1(v1.5.0+) Output file:PBI_Dataset_Health_$timestamp.csv
The Power BI Admin REST API does not expose byte-level dataset memory consumption. This document explains what IS available via the admin API, how it maps to performance risk, and where to go when you need actual memory numbers.
Each row is one dataset. Fields are built from the workspace $expand=datasets call β
no extra API calls are needed for the base output.
| Column | Source | Notes |
|---|---|---|
WorkspaceId |
Workspace object | |
WorkspaceName |
Workspace object | |
WorkspaceType |
Workspace object |
Shared or Personal
|
DatasetId |
Dataset object | |
DatasetName |
Dataset object | |
TargetStorageMode |
dataset.targetStorageMode |
Raw API value (see table below) |
StorageCategory |
Derived | Human-readable memory proxy |
IsRefreshable |
dataset.isRefreshable |
False for DirectQuery, push, streaming |
IsOnPremGatewayRequired |
dataset.isOnPremGatewayRequired |
On-premises data source dependency |
ConfiguredBy |
dataset.configuredBy |
Owner UPN |
LastRefreshStart |
Refresh history API | Requires -IncludeRefreshHistory
|
LastRefreshEnd |
Refresh history API | Requires -IncludeRefreshHistory
|
LastRefreshDurationMin |
Calculated |
(EndTime - StartTime) in minutes; proxy for dataset size |
LastRefreshStatus |
Refresh history API |
Completed | Failed | Cancelled
|
| API Value | StorageCategory | Memory Behaviour |
|---|---|---|
Abf |
Import (In-Memory) | Dataset loaded into Analysis Services vertipaq engine. Highest memory footprint. Stored as .abf compressed columnar format. |
PremiumFiles |
Import (Large Format) | Same in-memory engine but uses Premium large dataset storage (.pbi files, up to 400 GB). Even higher memory footprint. |
Pbix |
Import (In-Memory) | Older small-dataset import format. Same engine as Abf. |
DirectQuery |
DirectQuery (No Memory) | No data stored in Power BI. Every visual fires a query to the source. Zero memory footprint, but source database bears the query load. |
Streaming |
Streaming | Real-time push data. Memory footprint managed by the streaming engine, not vertipaq. |
CompositeModel |
Composite | Mix of Import tables and DirectQuery tables in one dataset. Memory footprint is proportional to the imported partition of the model. |
Rule of thumb: Any dataset where
StorageCategorystarts withImportis held in Analysis Services memory. If a Premium capacity is running hot, Import datasets are the first place to investigate.
When -IncludeRefreshHistory is specified, the script calls:
GET /v1.0/myorg/admin/datasets/{datasetId}/refreshes?$top=1
| Refresh Duration | Rough Signal |
|---|---|
| < 5 min | Small dataset; low memory risk |
| 5 β 30 min | Medium dataset; worth monitoring |
| 30 β 60 min | Large dataset; may strain capacity during peak hours |
| > 60 min | Very large dataset; review partitioning, incremental refresh, or Premium capacity sizing |
Refresh duration is influenced by source query time and network latency β not just model size β so treat it as a signal, not a precise measurement.
Performance note: This switch makes one API call per refreshable dataset. On large tenants (hundreds or thousands of datasets) this can take several minutes and may hit rate limits. The script adds a 200 ms delay between calls and handles errors per-dataset without stopping.
| Metric | Why Not Available | Where to Get It |
|---|---|---|
| Dataset memory size (bytes / MB) | Not exposed in any REST endpoint | XMLA endpoint DMV: SELECT * FROM $SYSTEM.DISCOVER_OBJECT_MEMORY_USAGE (Premium / Fabric only) |
| Per-table memory breakdown | Not in REST API | XMLA: SELECT * FROM $SYSTEM.DISCOVER_STORAGE_TABLES
|
| Query duration / render time | Not in Admin API | Azure Log Analytics β PowerBIActivity / AzureDiagnostics table |
| CPU consumption per dataset | Not in REST API | Fabric Capacity Metrics app (internal, no public API) |
| Throttling / overload events | Not in REST API | Fabric Capacity Metrics app or Azure Monitor alerts |
| Partition-level memory | Not in REST API | XMLA: SELECT * FROM $SYSTEM.DISCOVER_STORAGE_TABLE_COLUMNS
|
For tenants on Premium or Fabric capacity, true memory metrics are available via the
XMLA read endpoint. Connect with SQL Server Management Studio (SSMS) or DAX Studio
to the workspace XMLA endpoint (powerbi://api.powerbi.com/v1.0/myorg/WorkspaceName).
SELECT
OBJECT_PARENT_PATH,
OBJECT_NAME,
OBJECT_TYPE,
USED_SIZE / 1048576.0 AS UsedSizeMB,
CREATED_TIME
FROM $SYSTEM.DISCOVER_OBJECT_MEMORY_USAGE
ORDER BY USED_SIZE DESCSELECT
TABLE_ID,
USED_SIZE / 1048576.0 AS UsedSizeMB,
ROWS_COUNT
FROM $SYSTEM.DISCOVER_STORAGE_TABLES
ORDER BY USED_SIZE DESCSELECT
TABLE_ID,
COLUMN_ID,
COLUMN_TYPE,
USED_SIZE / 1048576.0 AS UsedSizeMB,
DICTIONARY_SIZE / 1048576.0 AS DictionarySizeMB
FROM $SYSTEM.DISCOVER_STORAGE_TABLE_COLUMNS
ORDER BY USED_SIZE DESCRequires the user or service principal to have XMLA Read access on the capacity (
Fabric Admin Portal β Capacity settings β Power BI workloads β XMLA Endpoint = Read).
If the workspace is linked to an Azure Log Analytics workspace
(Workspace Settings β Azure connections β Log Analytics), the following tables
are available in Log Analytics / Azure Monitor:
| Table | Useful Columns | What to Query |
|---|---|---|
PowerBIActivity |
DurationMs, DatasetName, WorkspaceName
|
Average query duration per dataset |
AzureDiagnostics |
duration_d, dataset_s
|
Refresh telemetry |
Example KQL β average query duration per dataset (last 7 days):
PowerBIActivity
| where TimeGenerated > ago(7d)
| where OperationName == "QueryEnd"
| summarize AvgDurationMs = avg(DurationMs), QueryCount = count()
by DatasetName, WorkspaceName
| order by AvgDurationMs desc.\Get-PBIWorkspaceUsageReport.ps1 `
-TenantId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" `
-ClientId "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy" `
-ClientSecret "your-secret"Produces PBI_Dataset_Health_$timestamp.csv with TargetStorageMode, StorageCategory,
IsRefreshable, IsOnPremGatewayRequired, ConfiguredBy β all columns populated.
LastRefresh* columns present but empty.
.\Get-PBIWorkspaceUsageReport.ps1 `
-TenantId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" `
-ClientId "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy" `
-ClientSecret "your-secret" `
-IncludeRefreshHistoryPopulates LastRefreshStart, LastRefreshEnd, LastRefreshDurationMin, LastRefreshStatus
for all IsRefreshable = True datasets.
The PBI_Usage_Summary_$timestamp.txt file now includes a DATASET STORAGE MODE BREAKDOWN
section showing a count of datasets per StorageCategory. Example output:
DATASET STORAGE MODE BREAKDOWN
(Import = held in Analysis Services memory; DirectQuery = no memory footprint)
Import (In-Memory) 142 dataset(s)
DirectQuery (No Memory) 38 dataset(s)
Composite 12 dataset(s)
Import (Large Format) 3 dataset(s)
A high ratio of Import datasets on a shared-capacity tenant is a common cause of slow report loads and refresh failures β this breakdown helps identify whether upgrading to Premium/Fabric would be beneficial.
Last updated: 2026-04-03 | Managed Solution β Will Ford See also: PBI Admin API Reference
- Overview
- Start-LyncCsvExporter
- Get-ComprehensiveLyncReport
- Get-LyncHealthReport
- Get-LyncInfrastructureReport
- Get-LyncServiceStatus
- Get-LyncUserRegistrationReport
- Export-ADLyncTeamsMigrationData
- New-Office365Accounts
- Sync-ContactsFromCsv
- Set-EmailToSharedAccount
- Set-SMTPForward
- Invoke-UserSignOutAndBlock
- Security Assessment Scripts (coming soon)
- Azure Automation (documentation pending)
- Get-GraphToken
- Get-GraphHeaders
- Get-AzureResourcePaging
- Get-EnterpriseAppUsage
- Get-ExchangeErrorsGraph
- Get-PBIWorkspaceUsageReport
- Intune Management (documentation pending)