وقتی حجم دادهها در Power BI افزایش پیدا میکند، یکی از اولین جاهایی که چالش عملکرد خودش را نشان میدهد، Measures در DAX است.
دلیل آن ساده است:
- DAX یک زبان Context-based است.
- Query Engine با هر کلیک کاربر محاسبات را در لحظه اجرا میکند.
- و اگر Measures درست طراحی نشده باشند، CPU ،RAM و VertiPaq را به شدت درگیر میکند.
سازمانهایی که از Power BI برای گزارشسازی مقیاس بزرگ استفاده میکنند (از جمله تجارت الکترونیک، بانکداری، Telco و تولید) نیازمند طراحی اصولی Measures و مدل داده هستند.
پیشنهاد مطالعه: VertiPaq Tuning راهکارهای عملی کوچکسازی مدل برای کاهش مصرف حافظه و افزایش سرعت گزارشها در Power BI
در این مقاله، از دید BI Analyst + Data Engineer + Performance Tuning به موضوع نگاه میکنیم و یک Playbook عملی برای بهینهسازی DAX ارائه میدهیم.
درک Engine Power BI (چیزی که همه نادیده میگیرند)
Power BI شامل دو موتور اصلی است:
| موتور | نقش | توضیح |
|---|---|---|
| VertiPaq Engine | Memory Storage | فشردهسازی ستونها و Load در RAM |
| Formula Engine | Query Execution | اجرای محاسبات DAX و پردازش Context |
نکته کلیدی: VertiPaq سریع است. Formula Engine کندتر است.
در نتیجه:
- هر Measure که Row Context → Filter Context → Row Context تبدیل کند، هزینه سنگین دارد.
- هر استفاده از CALCULATE + FILTER + ALL در اسلایسهای گسترده، فشار Formula Engine را بالا میبرد.
اصول طلایی طراحی مدل داده برای DAX
قبل از بهینهسازی Measures، مدل داده را درست کنید:
| راهکار | چرا مهم است؟ |
|---|---|
| استفاده از مدل Star Schema | کاهش Joinهای سنگین |
| جدا کردن Fact و Dimension | برای Context Clear و مناسب |
| حذف ستونهای غیرضروری | کاهش حجم Memory |
| استفاده از Data Types صحیح | پرفورمنس فشردهسازی VertiPaq |
نشانه اینکه مدل شما اشتباه است:
- تعداد زیادی Table با روابط Many-to-Many
- استفاده از DAX برای Join کردن جداول
- وجود Calculated Columnهای زیاد
قاعده اصلی: تا جایی که ممکن است Logic را در ETL یا SQL View انجام دهید، نه در DAX.
اصول طراحی Measure استاندارد
اشتباه رایج:
Total Sales :=
SUM(FactSales[Amount])
بهظاهر ساده است، اما اگر رابطهها مبهم باشند → Measure رفتار غیرقابلپیشبینی خواهد داشت.
نسخه صحیح:
Total Sales :=
SUMX(FactSales, FactSales[Amount])
SUMX از Row Context شروع میکند و سپس تبدیل به Filter Context میشود → رفتار کنترلشدهتر.
Anti-Patterns (الگوهای مخرب)
| Anti-Pattern | اثر مخرب |
|---|---|
| استفاده بیش از حد از CALCULATE() | فعالسازی بیش از حد Formula Engine |
| استفاده از Measures تودرتو | اجرای چندباره محاسبات |
| استفاده از FILTER(Table ,Condition) در هر Measure | اسکن کامل Fact Table |
| استفاده از ALL() بدون نیاز | از بین رفتن مزیت Context Filtering |
مثال بد:
Sales Last Year :=
CALCULATE([Total Sales], FILTER(ALL(FactSales), FactSales[Year] = MAX(FactSales[Year]) - 1))
نسخه بهینه:
Sales Last Year :=
CALCULATE([Total Sales], SAMEPERIODLASTYEAR(DimDate[Date]))
تکنیکهای بهینهسازی (Playbook عملی)
۱. تبدیل Measures به Intermediate Metrics
بهجای نوشتن یک Measure غولپیکر، آن را به چند Measure کوچک تقسیم کنید.
قبل:
Net Profit :=
SUM(FactSales[Amount]) - SUM(FactCost[Amount])
بعد:
Total Sales :=
SUM(FactSales[Amount])
Total Cost :=
SUM(FactCost[Amount])
Net Profit :=
[Total Sales] - [Total Cost]
نتیجه: با کش شدن Measures، Formula Engine نتایج را دوباره محاسبه نمیکند.
استفاده از Variables
مثال قبل را با VAR بهتر میکنیم:
Net Profit :=
VAR Sales = [Total Sales]
VAR Cost = [Total Cost]
RETURN Sales - Cost
مزیت:
- جلوگیری از اجرای چندباره محاسبات
- افزایش سرعت Pivot و Slicerها
کاهش Context Transition
از CALCULATE فقط وقتی نیاز است استفاده کنید.
استفاده از Aggregation Tables (مخصوص گزارشهای حجیم)
وقتی Fact Table بیش از ۳۰ میلیون رکورد دارد:
- یک Fact Aggregation بسازید.
- Power BI Aggregate Awareness دارد. (بهشرط رعایت نام ستونها)
تحلیل عملکرد Measure با Performance Analyzer
در Power BI:
View → Performance Analyzer
مهمترین آیتم:
- DAX Query
- Visual Display
- Other
اگر DAX Query زمان بالا دارد → Measure باید بهینه شود
اگر Visual Display بالا است → مدل/ویژوال سنگین است نه DAX
مثال واقعی (سناریوی E-Commerce)
حجم FactSales :۹۸ میلیون
کاربر نهایی: مدیر فروش
Measure سنگین اولیه:
Conversion Rate :=
DIVIDE([Total Orders], [Total Visitors])
بهینه:
Total Orders :=
CALCULATE(COUNTROWS(FactOrders))
Total Visitors :=
DISTINCTCOUNT(FactSessions[VisitorID])
Conversion Rate :=
VAR Orders = [Total Orders]
VAR Visitors = [Total Visitors]
RETURN DIVIDE(Orders, Visitors)
نتیجه:
در گزارش ۹ ویژوال → زمان رندر از ۲.۸s → ۰.۹s کاهش.
سوالات متداول (FAQ)
| سوال | پاسخ حرفهای |
|---|---|
| DAX سریعتر است یا SQL؟ | محاسبات Aggregation در DAX روی VertiPaq سریعتر است، ولی Transformation در SQL باید انجام شود. |
| Calculated Column خوب است؟ | فقط اگر قابل محاسبه در ETL نباشد. |
| DirectQuery باعث کندی گزارش میشود؟ | بله، زیرا Engine روی DB اجرا میشود نه RAM. |
خدمات داده و BI از لاندا
لاندا در پروژههای BI Enterprise خدمات زیر را ارائه میدهد:
✅ بهینهسازی مدل داده و DAX
✅ طراحی Report و Dashboard استاندارد
✅ استقرار Semantic Layer حرفهای
✅ آموزش تیم BI داخلی

و سپس «افزودن به صفحه اصلی» ضربه بزنید
و سپس «افزودن به صفحه اصلی» ضربه بزنید

نظری داده نشده