Session 30 — Data Modeling حرفهای در Power BI؛ Fact، Dimension، Star Schema، Grain و Relationship
Data Modeling حرفهای در Power BI؛ Fact، Dimension، Star Schema، Grain و Relationship
بخشی از آموزش جامع Power BI
محتوای درس Data Modeling حرفهای در Power BI؛ Fact، Dimension، Star Schema، Grain و Relationship
شروع جلسه؛ گزارش خوب از مدل خوب شروع میشود
خیلیها مستقیم میروند سراغ نمودار و DAX؛ ولی اگر مدل داده خراب باشد، بعداً هر Measure تبدیل به جنگ میشود. مدل خوب یعنی ساختاری که هم معنی کسبوکار را درست نشان بدهد، هم فیلترها قابل پیشبینی باشند و هم توسعه گزارش سادهتر شود.
در این جلسه از دید یک BI Developer واقعی مدل را طراحی میکنیم.
۳۰.۱. Data Model چیست؟
مدل داده مشخص میکند چه جدولهایی داریم، هر جدول چه Grainی دارد، جدولها چطور به هم مرتبطاند و فیلتر از کجا به کجا حرکت میکند.
۳۰.۲. Star Schema
در Star Schema معمولاً یک Fact مرکزی داریم و Dimensionها دور آن قرار میگیرند.
۳۰.۳. Fact Table
Fact جدول رخدادهای قابل اندازهگیری کسبوکار است؛ مثلاً فروش، سفارش، موجودی Snapshot یا پرداخت.
| ستون FactSales | نمونه |
|---|---|
| DateKey | 20260820 |
| ProductKey | 105 |
| CustomerKey | 3201 |
| BranchKey | 12 |
| Quantity | 3 |
| SalesAmount | 45,000,000 |
۳۰.۴. Dimension Table
Dimension جواب سؤالهای «چه کسی؟ چه چیزی؟ کجا؟ چه زمانی؟» را میدهد؛ مثل محصول، مشتری، شعبه و تاریخ.
۳۰.۵. Fact و Dimension را قاطی نکن
SalesAmount ویژگی محصول نیست؛ Fact است. ProductCategory مقدار اندازهگیریشونده فروش نیست؛ ویژگی Dimension محصول است.
۳۰.۶. Grain مهمترین سؤال مدل
Grain یعنی دقیقاً هر Row چه چیزی را نمایندگی میکند.
FactSales grain = one row per Order Line
قبل از طراحی Relationship و Measure باید Grain را به یک جمله واضح تبدیل کنی.
۳۰.۷. Grainهای مختلف
| جدول | Grain |
|---|---|
| FactSales | هر خط سفارش |
| FactInventorySnapshot | هر محصول-انبار-روز |
| FactTarget | هر شعبه-ماه |
| DimCustomer | هر مشتری |
۳۰.۸. چرا Grain حیاتی است؟
اگر FactSales در سطح OrderLine باشد، Count Rows تعداد سفارش نیست. یک سفارش میتواند چند Line داشته باشد. همین اشتباه ساده KPI را خراب میکند.
۳۰.۹. طراحی از Business Process
اول فرآیند کسبوکار را مشخص کن؛ بعد Grain، Factها، Dimensionها و در آخر Relationshipها.
۳۰.۱۰. Measureهای Additive
SalesAmount معمولاً روی محصول، مشتری و زمان قابل جمع است؛ پس یک Fact Additive محسوب میشود.
۳۰.۱۱. Semi-Additive
موجودی پایان روز را نمیتوان مثل فروش روی روزها جمع کرد. موجودی Snapshot روی بعضی Dimensionها جمعپذیر است ولی روی زمان معمولاً نیازمند منطق متفاوت است.
۳۰.۱۲. Non-Additive
درصد، Ratio و Average معمولاً نباید مثل Amount خام جمع شوند. بهتر است اجزای پایه ذخیره شوند و Measure درست ساخته شود.
۳۰.۱۳. Dimension Date
تقریباً هر مدل تحلیلی جدی به Date Dimension استاندارد نیاز دارد؛ Year، Quarter، Month، Week و ویژگیهای تقویمی در آن نگهداری میشوند.
۳۰.۱۴. Role-playing Date
یک Fact ممکن است OrderDate، ShipDate و DueDate داشته باشد. یک DimDate میتواند نقشهای مختلف زمانی داشته باشد، اما Relationshipهای Active/Inactive باید آگاهانه طراحی شوند.
۳۰.۱۵. Surrogate Key
در مدلهای انبار داده معمولاً Dimension یک کلید داخلی مثل ProductKey دارد که از Business Code جداست.
ProductKey = 105
ProductCode = IK-AX-220
۳۰.۱۶. چرا Surrogate Key؟
برای مدیریت تاریخچه، تغییر Business Key، یکپارچهسازی چند منبع و کنترل مدل میتواند بسیار مفید باشد.
۳۰.۱۷. Business Key
Business Key کلیدی است که سیستم کسبوکار میشناسد؛ مثل CustomerCode. قبل از Mapping باید کیفیت و یکتایی آن را بررسی کنی.
۳۰.۱۸. Relationship One-to-Many
الگوی استاندارد Star Schema این است که Dimension در سمت One و Fact در سمت Many باشد.
DimProduct[ProductKey] 1 → * FactSales[ProductKey]
۳۰.۱۹. سمت One باید یکتا باشد
اگر ProductKey در DimProduct Duplicate باشد، Relationship استاندارد Many-to-One مشکل پیدا میکند. Duplicate را در ETL حل یا علتش را مدل کن.
۳۰.۲۰. Cardinality
| نوع | کاربرد |
|---|---|
| One-to-Many | الگوی اصلی Dimension → Fact |
| One-to-One | کمتر رایج |
| Many-to-Many | سناریوهای خاص؛ نیازمند دقت |
۳۰.۲۱. Filter Direction
در مدل ستارهای معمولاً فیلتر از Dimension به Fact حرکت میکند. این رفتار ساده و قابل پیشبینی است.
۳۰.۲۲. Both Direction
Cross Filter Both گاهی لازم است، ولی استفاده بیدلیل میتواند Ambiguity و نتایج سختفهم ایجاد کند.
Single Direction را Default ذهنی قرار بده مگر اینکه دلیل مدلسازی روشن داشته باشی.
۳۰.۲۳. Active Relationship
بین دو جدول ممکن است چند مسیر رابطه وجود داشته باشد ولی فقط رابطه مناسب Active باشد. DAX میتواند در سناریوهای لازم از رابطه Inactive استفاده کند.
۳۰.۲۴. Many-to-Many
Many-to-Many ذاتاً ممنوع نیست، اما قبل از استفاده بررسی کن آیا Bridge Table طراحی تمیزتری میدهد.
۳۰.۲۵. Bridge Table
مثلاً یک Customer میتواند چند Segment داشته باشد و هر Segment چند Customer. BridgeCustomerSegment میتواند رابطه را مدل کند.
۳۰.۲۶. Snowflake یا Star؟
Snowflake Dimensionها را بیشتر نرمال میکند. در Power BI اغلب Star Schema سادهتر برای مصرف گزارش و DAX مناسب است، مگر دلیل مشخصی برای Snowflake داشته باشی.
۳۰.۲۷. مدل عملیاتی را عیناً وارد BI نکن
دیتابیس OLTP برای ثبت تراکنش طراحی شده، نه الزاماً تحلیل. دهها جدول نرمالشده را بدون طراحی تحلیلی وارد Power BI نکن.
۳۰.۲۸. Flatten Dimension
در بسیاری از مدلها Product، Category و Brand را میتوان در یک DimProduct تحلیلی نگه داشت تا مدل سادهتر شود.
۳۰.۲۹. Factless Fact
گاهی رخداد داریم ولی Measure عددی واضح نداریم؛ مثلاً حضور کارمند در دوره آموزشی. Factless Fact برای ثبت رابطه رخدادها کاربرد دارد.
۳۰.۳۰. Degenerate Dimension
شماره سفارش ممکن است در Fact بماند بدون اینکه Dimension جداگانهای برای Order بسازیم؛ این مفهوم Degenerate Dimension است.
۳۰.۳۱. Junk Dimension
چند Flag کمحجم و پراکنده را گاهی میتوان در یک Junk Dimension ترکیب کرد؛ بیشتر در طراحیهای DW کلاسیک دیده میشود.
۳۰.۳۲. Unknown Member
اگر Fact به ProductKey نامعتبر اشاره کند، حذف Fact ممکن است Total را کم کند. یک Unknown Member کنترلشده میتواند کمک کند داده حفظ و مشکل Master Data قابل مشاهده بماند.
۳۰.۳۳. Slowly Changing Dimension
اگر Segment مشتری یا Region شعبه در طول زمان تغییر کند، باید تصمیم بگیری تاریخچه برای تحلیل مهم است یا فقط مقدار فعلی.
۳۰.۳۴. SCD Type 1
مقدار قبلی با مقدار جدید جایگزین میشود. برای اصلاح غلط املایی یا ویژگیهایی که تاریخچهشان مهم نیست مناسب است.
۳۰.۳۵. SCD Type 2
برای تغییر مهم، Row جدید با Surrogate Key جدید و بازه اعتبار ساخته میشود تا Fact تاریخی به نسخه درست Dimension وصل بماند.
۳۰.۳۶. مثال Customer Segment
| CustomerKey | CustomerCode | Segment | ValidFrom | ValidTo |
|---|---|---|---|---|
| 101 | C001 | Silver | 2025-01-01 | 2025-12-31 |
| 205 | C001 | Gold | 2026-01-01 | ... |
۳۰.۳۷. چند Fact Table
مدل میتواند FactSales، FactTarget و FactInventory داشته باشد. لازم نیست همه چیز را در یک Fact غولآسا بریزی.
۳۰.۳۸. Conformed Dimensions
اگر FactSales و FactTarget هر دو از DimDate و DimBranch استاندارد استفاده کنند، مقایسه Actual و Target بسیار تمیزتر میشود.
۳۰.۳۹. Fact-to-Fact Relationship
وصل کردن مستقیم FactSales به FactTarget معمولاً انتخاب اول خوبی نیست. بهتر است هر دو از Dimensionهای مشترک فیلتر شوند.
۳۰.۴۰. Grain متفاوت Actual و Target
FactSales: Branch-Product-Day
FactTarget: Branch-Month
این دو Fact Grain متفاوت دارند. مقایسه باید با Dimensionهای مشترک و Measure درست انجام شود.
۳۰.۴۱. مثال شرکت هانا
| جدول | نقش |
|---|---|
| FactSales | فروش واقعی |
| FactTarget | هدف ماهانه |
| DimDate | زمان |
| DimProduct | محصول |
| DimCustomer | مشتری |
| DimBranch | شعبه |
۳۰.۴۲. مدل فروش شرکت هانا
FactSales در Grain خط سفارش است. DimProduct و DimCustomer و DimBranch سمت One هستند. DimDate بر اساس OrderDate رابطه Active دارد.
۳۰.۴۳. کنترل Referential Integrity
برای هر Foreign Key در Fact بررسی کن آیا Key متناظر در Dimension وجود دارد. Anti Join در Power Query برای این کنترل عالی است.
۳۰.۴۴. Hide Technical Columns
کلیدهای فنی مثل ProductKey یا ستونهای ETL لازم نیست در Field List کاربر نهایی دیده شوند. مدل را برای مصرفکننده تمیز کن.
۳۰.۴۵. Naming
نام جدول و ستون باید کسبوکاری و قابل فهم باشد. نامهایی مثل Table1، qry2 و Column17 در مدل نهایی حرفهای نیستند.
۳۰.۴۶. Measures Table
در بعضی پروژهها Measureها را در یک جدول اختصاصی سازماندهی میکنند. مهمتر از محل، Naming و Folder بندی منطقی Measureهاست.
۳۰.۴۷. Hierarchy
Hierarchyهایی مثل Year → Quarter → Month یا Category → Subcategory → Product میتوانند تجربه گزارش را بهتر کنند.
۳۰.۴۸. Sort By Column
نام ماه را بر اساس MonthNumber مرتب کن تا April و August به ترتیب الفبایی نمایش داده نشوند.
۳۰.۴۹. Data Category
برای ستونهایی مثل City، Country، URL یا Geographic fields، Data Category مناسب میتواند رفتار Visualها را بهتر کند.
۳۰.۵۰. مدل باریک بهتر است
ستونهای غیرضروری را وارد مدل نکن. هر ستون حافظه مصرف میکند و Field List را شلوغ میکند.
۳۰.۵۱. High Cardinality Columns
ستونهای متنی با مقادیر تقریباً یکتا مثل GUID یا توضیح بلند میتوانند مدل را سنگین کنند. اگر برای تحلیل لازم نیستند، حذف یا خارج از مدل نگه داشتنشان را بررسی کن.
۳۰.۵۲. DateTime
اگر تحلیل در سطح Date است، نگه داشتن Time در همان ستون ممکن است Cardinality را بالا ببرد. طراحی را بر اساس نیاز واقعی انجام بده.
۳۰.۵۳. Calculated Column یا Power Query؟
اگر Transformation در زمان Refresh قابل انجام است، Power Query اغلب گزینه قابل بررسی است. Calculated Column در مدل هم کاربرد خودش را دارد؛ انتخاب به Context و معماری بستگی دارد.
۳۰.۵۴. Measure یا Calculated Column؟
Measure برای محاسبه پویا در Filter Context است. اگر مقدار باید برای هر Row ذخیره شود، Calculated Column مفهوم متفاوتی دارد. این تفاوت را در فصل DAX عمیق میکنیم.
۳۰.۵۵. Auto Date/Time
برای پروژه حرفهای معمولاً Date Dimension کنترلشده بهتر از تکیه کامل بر Auto Date/Time است.
۳۰.۵۶. Ambiguous Paths
اگر چند مسیر فیلتر بین جدولها ایجاد کنی، مدل میتواند مبهم شود. این یکی از دلایل پرهیز از Both Direction بیدلیل است.
۳۰.۵۷. Circular Relationship
مدل را طوری طراحی نکن که حلقههای رابطهای غیرضروری ایجاد شوند. Star Schema ساده بسیاری از این مشکلات را از ابتدا کم میکند.
۳۰.۵۸. Model View
در Model View جدولها را منظم بچین: Factها وسط، Dimensionها اطراف. Layout خوب خودش مستندات زنده مدل است.
۳۰.۵۹. مستندسازی Relationship
| From | To | Cardinality | Direction |
|---|---|---|---|
| DimProduct | FactSales | 1:* | Single |
| DimCustomer | FactSales | 1:* | Single |
| DimBranch | FactSales | 1:* | Single |
| DimDate | FactSales | 1:* | Single |
۳۰.۶۰. تست مدل
یک Product را فیلتر کن و بررسی کن فقط FactSales مربوط به آن تغییر کند. یک Branch و Month را ترکیب کن و KPIها را با داده منبع تطبیق بده.
۳۰.۶۱. Reconciliation
قبل از ساخت Dashboard جذاب، Total Sales، تعداد سفارش و چند نمونه مشتری/محصول را با Source تطبیق بده.
۳۰.۶۲. خطای رایج؛ یک جدول بزرگ
Merge کردن همه Dimensionها داخل Fact و ساخت یک Flat Table بزرگ ممکن است در پروژه کوچک جواب بدهد، ولی مقیاسپذیری، تکرار داده و نگهداری را سخت میکند.
۳۰.۶۳. خطای رایج؛ Relationship با Text Name
نام محصول یا مشتری ممکن است تکراری یا متغیر باشد. Relationship را روی Key قابل اعتماد بساز.
۳۰.۶۴. خطای رایج؛ Many-to-Many برای حل سریع
اگر Relationship معمولی Error میدهد، سریع Cardinality را Many-to-Many نکن. اول Duplicate و Grain را بررسی کن.
۳۰.۶۵. خطای رایج؛ Both برای درست شدن Visual
اگر Visual با Both درست شد ولی نمیدانی چرا، مدل هنوز نیاز به تحلیل دارد. Cross-filter direction باید تصمیم آگاهانه باشد.
۳۰.۶۶. Best Practiceها
Business Process را اول مشخص کن.
Grain هر Fact را یک جمله بنویس.
Dimension سمت One باید Key یکتا داشته باشد.
Star Schema را Default طراحی قرار بده.
Single Direction را تا وقتی دلیل نداری حفظ کن.
Factها را مستقیم به هم وصل نکن مگر طراحی مشخص داشته باشی.
Conformed Dimension بساز.
ستونهای غیرضروری و High Cardinality را کنترل کن.
مدل را با Source Reconcile کن.
۳۰.۶۷. تمرین پایه
برای فروشگاه فرضی FactSales، DimProduct، DimCustomer و DimDate را طراحی کن و Grain هر جدول را بنویس.
۳۰.۶۸. تمرین Cardinality
DimProduct دارای ProductKey تکراری است. توضیح بده چرا Relationship 1:* مشکل دارد و قبل از تغییر Cardinality چه چیزی را باید بررسی کنی.
۳۰.۶۹. تمرین Actual vs Target
FactSales در Grain روزانه-محصول-شعبه و FactTarget در Grain ماهانه-شعبه است. Dimensionهای مشترک و مسیر فیلتر را طراحی کن.
۳۰.۷۰. تمرین SCD
مشتری از Segment Silver به Gold تغییر کرده. دو سناریوی Type 1 و Type 2 را مقایسه کن و اثرشان روی گزارش فروش سال قبل را توضیح بده.
۳۰.۷۱. پروژه Session؛ Star Schema شرکت هانا
| خروجی | شرح |
|---|---|
| FactSales | OrderLine grain |
| FactTarget | Branch-Month grain |
| DimDate | Calendar attributes |
| DimProduct | Product master |
| DimCustomer | Customer master |
| DimBranch | Branch/Region |
| Relationships | 1:* Single |
| QA | Orphans + totals |
در پایان باید Model View تمیز، Grain مستند، Relationshipهای مشخص و کنترل Orphan Key داشته باشی.
جمعبندی Session 30
مدلسازی خوب یعنی قبل از DAX تکلیف معنی داده را روشن کنیم. اگر Grain و Relationship درست باشند، بخش بزرگی از DAX سادهتر و قابل اعتمادتر میشود.
Business process → Grain → Facts + Dimensions → Relationships → Validation
Session 31 را وارد DAX میکنیم: Measure، Calculated Column، Row Context، Filter Context و اولین Measureهای حرفهای فروش.