@luquimbo/bi-superpowers 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/.claude-plugin/plugin.json +8 -0
  2. package/.mcp.json +25 -0
  3. package/AGENTS.md +244 -0
  4. package/CHANGELOG.md +265 -0
  5. package/LICENSE +21 -0
  6. package/README.md +211 -0
  7. package/bin/build-plugin.js +30 -0
  8. package/bin/cli.js +1064 -0
  9. package/bin/commands/add.js +533 -0
  10. package/bin/commands/add.test.js +77 -0
  11. package/bin/commands/build-desktop.js +166 -0
  12. package/bin/commands/changelog.js +443 -0
  13. package/bin/commands/diff.js +325 -0
  14. package/bin/commands/lint.js +419 -0
  15. package/bin/commands/lint.test.js +103 -0
  16. package/bin/commands/mcp-setup.js +246 -0
  17. package/bin/commands/pull.js +287 -0
  18. package/bin/commands/pull.test.js +36 -0
  19. package/bin/commands/push.js +231 -0
  20. package/bin/commands/push.test.js +14 -0
  21. package/bin/commands/search.js +344 -0
  22. package/bin/commands/search.test.js +115 -0
  23. package/bin/commands/setup.js +545 -0
  24. package/bin/commands/setup.test.js +46 -0
  25. package/bin/commands/sync-profile.js +405 -0
  26. package/bin/commands/sync-profile.test.js +14 -0
  27. package/bin/commands/sync-source.js +418 -0
  28. package/bin/commands/sync-source.test.js +14 -0
  29. package/bin/commands/watch.js +206 -0
  30. package/bin/lib/generators/claude-plugin.js +266 -0
  31. package/bin/lib/generators/claude-plugin.test.js +110 -0
  32. package/bin/lib/generators/index.js +116 -0
  33. package/bin/lib/generators/shared.js +282 -0
  34. package/bin/lib/licensing/index.js +35 -0
  35. package/bin/lib/licensing/storage.js +364 -0
  36. package/bin/lib/licensing/storage.test.js +55 -0
  37. package/bin/lib/licensing/validator.js +213 -0
  38. package/bin/lib/licensing/validator.test.js +137 -0
  39. package/bin/lib/microsoft-mcp.js +176 -0
  40. package/bin/lib/microsoft-mcp.test.js +106 -0
  41. package/bin/lib/skills.js +84 -0
  42. package/bin/mcp/powerbi-modeling-launcher.js +38 -0
  43. package/bin/postinstall.js +44 -0
  44. package/bin/utils/errors.js +159 -0
  45. package/bin/utils/git.js +298 -0
  46. package/bin/utils/logger.js +142 -0
  47. package/bin/utils/mcp-detect.js +274 -0
  48. package/bin/utils/mcp-detect.test.js +105 -0
  49. package/bin/utils/pbix.js +305 -0
  50. package/bin/utils/pbix.test.js +37 -0
  51. package/bin/utils/profiles.js +312 -0
  52. package/bin/utils/projects.js +168 -0
  53. package/bin/utils/readline.js +206 -0
  54. package/bin/utils/readline.test.js +47 -0
  55. package/bin/utils/tui.js +314 -0
  56. package/bin/utils/tui.test.js +127 -0
  57. package/commands/contributions.md +265 -0
  58. package/commands/data-model-design.md +468 -0
  59. package/commands/dax-doctor.md +248 -0
  60. package/commands/fabric-scripts.md +452 -0
  61. package/commands/migration-assistant.md +290 -0
  62. package/commands/model-documenter.md +242 -0
  63. package/commands/pbi-connect.md +239 -0
  64. package/commands/project-kickoff.md +905 -0
  65. package/commands/report-layout.md +296 -0
  66. package/commands/rls-design.md +533 -0
  67. package/commands/theme-tweaker.md +624 -0
  68. package/config.example.json +23 -0
  69. package/config.json +23 -0
  70. package/desktop-extension/manifest.json +37 -0
  71. package/desktop-extension/package.json +10 -0
  72. package/desktop-extension/server.js +95 -0
  73. package/docs/openrouter-free-models.md +92 -0
  74. package/library/examples/README.md +151 -0
  75. package/library/examples/finance-reporting/README.md +351 -0
  76. package/library/examples/finance-reporting/data-model.md +267 -0
  77. package/library/examples/finance-reporting/measures.dax +557 -0
  78. package/library/examples/hr-analytics/README.md +371 -0
  79. package/library/examples/hr-analytics/data-model.md +315 -0
  80. package/library/examples/hr-analytics/measures.dax +460 -0
  81. package/library/examples/marketing-analytics/README.md +37 -0
  82. package/library/examples/marketing-analytics/data-model.md +62 -0
  83. package/library/examples/marketing-analytics/measures.dax +110 -0
  84. package/library/examples/retail-analytics/README.md +439 -0
  85. package/library/examples/retail-analytics/data-model.md +288 -0
  86. package/library/examples/retail-analytics/measures.dax +481 -0
  87. package/library/examples/supply-chain/README.md +37 -0
  88. package/library/examples/supply-chain/data-model.md +69 -0
  89. package/library/examples/supply-chain/measures.dax +77 -0
  90. package/library/examples/udf-library/README.md +228 -0
  91. package/library/examples/udf-library/functions.dax +571 -0
  92. package/library/snippets/dax/README.md +292 -0
  93. package/library/snippets/dax/business-domains.md +576 -0
  94. package/library/snippets/dax/calculate-patterns.md +276 -0
  95. package/library/snippets/dax/calculation-groups.md +489 -0
  96. package/library/snippets/dax/error-handling.md +495 -0
  97. package/library/snippets/dax/iterators-and-aggregations.md +474 -0
  98. package/library/snippets/dax/kpis-and-metrics.md +293 -0
  99. package/library/snippets/dax/rankings-and-topn.md +235 -0
  100. package/library/snippets/dax/security-patterns.md +413 -0
  101. package/library/snippets/dax/text-and-formatting.md +316 -0
  102. package/library/snippets/dax/time-intelligence.md +196 -0
  103. package/library/snippets/dax/user-defined-functions.md +477 -0
  104. package/library/snippets/dax/virtual-tables.md +546 -0
  105. package/library/snippets/excel-formulas/README.md +84 -0
  106. package/library/snippets/excel-formulas/aggregations.md +330 -0
  107. package/library/snippets/excel-formulas/dates-and-times.md +361 -0
  108. package/library/snippets/excel-formulas/dynamic-arrays.md +314 -0
  109. package/library/snippets/excel-formulas/lookups.md +169 -0
  110. package/library/snippets/excel-formulas/text-functions.md +363 -0
  111. package/library/snippets/governance/naming-conventions.md +97 -0
  112. package/library/snippets/governance/review-checklists.md +107 -0
  113. package/library/snippets/power-query/README.md +389 -0
  114. package/library/snippets/power-query/api-integration.md +707 -0
  115. package/library/snippets/power-query/connections.md +434 -0
  116. package/library/snippets/power-query/data-cleaning.md +298 -0
  117. package/library/snippets/power-query/error-handling.md +526 -0
  118. package/library/snippets/power-query/parameters.md +350 -0
  119. package/library/snippets/power-query/performance.md +506 -0
  120. package/library/snippets/power-query/transformations.md +330 -0
  121. package/library/snippets/report-design/accessibility.md +78 -0
  122. package/library/snippets/report-design/chart-selection.md +54 -0
  123. package/library/snippets/report-design/layout-patterns.md +87 -0
  124. package/library/templates/data-models/README.md +93 -0
  125. package/library/templates/data-models/finance-model.md +627 -0
  126. package/library/templates/data-models/retail-star-schema.md +473 -0
  127. package/library/templates/excel/README.md +83 -0
  128. package/library/templates/excel/budget-tracker.md +432 -0
  129. package/library/templates/excel/data-entry-form.md +533 -0
  130. package/library/templates/power-bi/README.md +72 -0
  131. package/library/templates/power-bi/finance-report.md +449 -0
  132. package/library/templates/power-bi/kpi-scorecard.md +461 -0
  133. package/library/templates/power-bi/sales-dashboard.md +281 -0
  134. package/library/themes/excel/README.md +436 -0
  135. package/library/themes/power-bi/README.md +271 -0
  136. package/library/themes/power-bi/accessible.json +307 -0
  137. package/library/themes/power-bi/bi-superpowers-default.json +858 -0
  138. package/library/themes/power-bi/corporate-blue.json +291 -0
  139. package/library/themes/power-bi/dark-mode.json +291 -0
  140. package/library/themes/power-bi/minimal.json +292 -0
  141. package/library/themes/power-bi/print-friendly.json +309 -0
  142. package/package.json +93 -0
  143. package/skills/contributions/SKILL.md +267 -0
  144. package/skills/data-model-design/SKILL.md +470 -0
  145. package/skills/data-modeling/SKILL.md +254 -0
  146. package/skills/data-quality/SKILL.md +664 -0
  147. package/skills/dax/SKILL.md +708 -0
  148. package/skills/dax-doctor/SKILL.md +250 -0
  149. package/skills/dax-udf/SKILL.md +489 -0
  150. package/skills/deployment/SKILL.md +320 -0
  151. package/skills/excel-formulas/SKILL.md +463 -0
  152. package/skills/fabric-scripts/SKILL.md +454 -0
  153. package/skills/fast-standard/SKILL.md +509 -0
  154. package/skills/governance/SKILL.md +205 -0
  155. package/skills/migration-assistant/SKILL.md +292 -0
  156. package/skills/model-documenter/SKILL.md +244 -0
  157. package/skills/pbi-connect/SKILL.md +241 -0
  158. package/skills/power-query/SKILL.md +406 -0
  159. package/skills/project-kickoff/SKILL.md +907 -0
  160. package/skills/query-performance/SKILL.md +480 -0
  161. package/skills/report-design/SKILL.md +207 -0
  162. package/skills/report-layout/SKILL.md +298 -0
  163. package/skills/rls-design/SKILL.md +535 -0
  164. package/skills/semantic-model/SKILL.md +237 -0
  165. package/skills/testing-validation/SKILL.md +643 -0
  166. package/skills/theme-tweaker/SKILL.md +626 -0
  167. package/src/content/base.md +237 -0
  168. package/src/content/mcp-requirements.json +69 -0
  169. package/src/content/routing.md +203 -0
  170. package/src/content/skills/contributions.md +259 -0
  171. package/src/content/skills/data-model-design.md +462 -0
  172. package/src/content/skills/data-modeling.md +246 -0
  173. package/src/content/skills/data-quality.md +656 -0
  174. package/src/content/skills/dax-doctor.md +242 -0
  175. package/src/content/skills/dax-udf.md +481 -0
  176. package/src/content/skills/dax.md +700 -0
  177. package/src/content/skills/deployment.md +312 -0
  178. package/src/content/skills/excel-formulas.md +455 -0
  179. package/src/content/skills/fabric-scripts.md +446 -0
  180. package/src/content/skills/fast-standard.md +501 -0
  181. package/src/content/skills/governance.md +197 -0
  182. package/src/content/skills/migration-assistant.md +284 -0
  183. package/src/content/skills/model-documenter.md +236 -0
  184. package/src/content/skills/pbi-connect.md +233 -0
  185. package/src/content/skills/power-query.md +398 -0
  186. package/src/content/skills/project-kickoff.md +899 -0
  187. package/src/content/skills/query-performance.md +472 -0
  188. package/src/content/skills/report-design.md +199 -0
  189. package/src/content/skills/report-layout.md +290 -0
  190. package/src/content/skills/rls-design.md +527 -0
  191. package/src/content/skills/semantic-model.md +229 -0
  192. package/src/content/skills/testing-validation.md +635 -0
  193. package/src/content/skills/theme-tweaker.md +618 -0
@@ -0,0 +1,506 @@
1
+ # Performance Optimization in Power Query
2
+
3
+ Best practices and patterns for optimizing Power Query performance, with emphasis on query folding.
4
+
5
+ ---
6
+
7
+ ## Query Folding Basics
8
+
9
+ ### What is Query Folding?
10
+
11
+ Query folding translates Power Query (M) operations into native database queries (SQL). This pushes processing to the data source, reducing data transfer and improving performance.
12
+
13
+ ### Check if Step Folds
14
+
15
+ Right-click any step > "View Native Query"
16
+ - If available: Step folds
17
+ - If grayed out: Step breaks folding
18
+
19
+ ### Operations That Typically Fold
20
+
21
+ | Operation | SQL Equivalent |
22
+ |-----------|---------------|
23
+ | `Table.SelectRows` | WHERE |
24
+ | `Table.SelectColumns` | SELECT |
25
+ | `Table.Sort` | ORDER BY |
26
+ | `Table.Group` | GROUP BY |
27
+ | `Table.NestedJoin` | JOIN |
28
+ | `Table.Distinct` | DISTINCT |
29
+ | `Table.FirstN` | TOP / LIMIT |
30
+ | `Table.Skip` | OFFSET |
31
+
32
+ ### Operations That Break Folding
33
+
34
+ | Operation | Why |
35
+ |-----------|-----|
36
+ | `Table.AddColumn` with custom function | Custom M logic |
37
+ | `Table.Buffer` | Explicit materialization |
38
+ | `Table.FromList` | Memory operations |
39
+ | `List.Generate` | Iterative logic |
40
+ | `Text.Proper`, `Text.Trim` (sometimes) | Source-specific |
41
+ | Accessing other queries | Cross-query dependency |
42
+
43
+ ---
44
+
45
+ ## Optimize Filter Order
46
+
47
+ ### Push Filters Early
48
+
49
+ ```m
50
+ let
51
+ // GOOD: Filter first, then transform
52
+ Source = Sql.Database("server", "database"),
53
+ Sales = Source{[Schema="dbo", Item="Sales"]}[Data],
54
+
55
+ // Step 1: Filter (folds to WHERE)
56
+ FilteredRows = Table.SelectRows(Sales, each [Year] = 2024),
57
+
58
+ // Step 2: Select columns (folds to SELECT)
59
+ SelectColumns = Table.SelectColumns(FilteredRows, {"Date", "Amount", "CustomerID"}),
60
+
61
+ // Step 3: Transform (may break folding - but on smaller dataset)
62
+ Transformed = Table.TransformColumns(SelectColumns, {{"Amount", each _ * 1.1}})
63
+ in
64
+ Transformed
65
+ ```
66
+
67
+ ### Anti-Pattern: Late Filtering
68
+
69
+ ```m
70
+ let
71
+ // BAD: Transform first, filter later
72
+ Source = Sql.Database("server", "database"),
73
+ Sales = Source{[Schema="dbo", Item="Sales"]}[Data],
74
+
75
+ // This might break folding
76
+ Transformed = Table.TransformColumns(Sales, {{"Amount", each _ * 1.1}}),
77
+
78
+ // Now filtering happens in memory (slow!)
79
+ FilteredRows = Table.SelectRows(Transformed, each [Year] = 2024)
80
+ in
81
+ FilteredRows
82
+ ```
83
+
84
+ ---
85
+
86
+ ## Column Selection Optimization
87
+
88
+ ### Select Only Needed Columns
89
+
90
+ ```m
91
+ let
92
+ Source = Sql.Database("server", "database"),
93
+ Sales = Source{[Schema="dbo", Item="Sales"]}[Data],
94
+
95
+ // GOOD: Select columns early
96
+ SelectedColumns = Table.SelectColumns(Sales, {
97
+ "OrderID", "CustomerID", "Amount", "OrderDate"
98
+ }),
99
+
100
+ // Remaining operations on fewer columns
101
+ Filtered = Table.SelectRows(SelectedColumns, each [Amount] > 100)
102
+ in
103
+ Filtered
104
+ ```
105
+
106
+ ### Remove Unnecessary Columns
107
+
108
+ ```m
109
+ let
110
+ Source = YourSource,
111
+
112
+ // Remove columns you don't need
113
+ RemovedColumns = Table.RemoveColumns(Source, {
114
+ "InternalID", "CreatedBy", "ModifiedBy", "Notes"
115
+ })
116
+ in
117
+ RemovedColumns
118
+ ```
119
+
120
+ ---
121
+
122
+ ## Avoid Row-by-Row Operations
123
+
124
+ ### Use Native Functions Instead
125
+
126
+ ```m
127
+ let
128
+ Source = YourSource,
129
+
130
+ // BAD: Row-by-row with List operations
131
+ BadPattern = Table.AddColumn(Source, "Total",
132
+ each List.Sum({[Price1], [Price2], [Price3]})
133
+ ),
134
+
135
+ // GOOD: Direct column reference
136
+ GoodPattern = Table.AddColumn(Source, "Total",
137
+ each [Price1] + [Price2] + [Price3], type number
138
+ )
139
+ in
140
+ GoodPattern
141
+ ```
142
+
143
+ ### Bulk Transformations
144
+
145
+ ```m
146
+ let
147
+ Source = YourSource,
148
+
149
+ // BAD: Multiple Table.AddColumn calls
150
+ Step1 = Table.AddColumn(Source, "Year", each Date.Year([Date])),
151
+ Step2 = Table.AddColumn(Step1, "Month", each Date.Month([Date])),
152
+ Step3 = Table.AddColumn(Step2, "Day", each Date.Day([Date])),
153
+
154
+ // BETTER: Transform existing columns where possible
155
+ BetterPattern = Table.TransformColumns(Source, {
156
+ {"DateColumn", Date.Year, Int64.Type} // Replaces column with year
157
+ })
158
+ in
159
+ Step3 // or BetterPattern depending on need
160
+ ```
161
+
162
+ ---
163
+
164
+ ## Table.Buffer Usage
165
+
166
+ ### When to Buffer
167
+
168
+ ```m
169
+ let
170
+ Source = YourSource,
171
+
172
+ // Buffer when table is used multiple times
173
+ BufferedSource = Table.Buffer(Source),
174
+
175
+ // Multiple references to buffered table
176
+ MaxValue = List.Max(BufferedSource[Amount]),
177
+ MinValue = List.Min(BufferedSource[Amount]),
178
+
179
+ Result = Table.AddColumn(BufferedSource, "Normalized",
180
+ each ([Amount] - MinValue) / (MaxValue - MinValue)
181
+ )
182
+ in
183
+ Result
184
+ ```
185
+
186
+ ### When NOT to Buffer
187
+
188
+ ```m
189
+ let
190
+ // DON'T buffer if query folds
191
+ Source = Sql.Database("server", "database"),
192
+ Sales = Source{[Schema="dbo", Item="Sales"]}[Data],
193
+
194
+ // This would break folding and load all data
195
+ // AVOID: Buffered = Table.Buffer(Sales)
196
+
197
+ // Let the filter fold instead
198
+ Filtered = Table.SelectRows(Sales, each [Year] = 2024)
199
+ in
200
+ Filtered
201
+ ```
202
+
203
+ ---
204
+
205
+ ## Partitioning Strategies
206
+
207
+ ### Process Large Data in Chunks
208
+
209
+ ```m
210
+ let
211
+ // Get distinct years for partitioning
212
+ Source = Sql.Database("server", "database"),
213
+ Sales = Source{[Schema="dbo", Item="Sales"]}[Data],
214
+
215
+ Years = List.Distinct(Table.Column(Sales, "Year")),
216
+
217
+ // Process each year separately (folded)
218
+ ProcessYear = (year as number) =>
219
+ let
220
+ Filtered = Table.SelectRows(Sales, each [Year] = year),
221
+ Transformed = Table.TransformColumns(Filtered, {
222
+ {"Amount", each _ * 1.1}
223
+ })
224
+ in
225
+ Transformed,
226
+
227
+ // Combine results
228
+ AllYears = Table.Combine(List.Transform(Years, ProcessYear))
229
+ in
230
+ AllYears
231
+ ```
232
+
233
+ ### Incremental Refresh Pattern
234
+
235
+ ```m
236
+ let
237
+ // Parameters for incremental refresh
238
+ RangeStart = #datetime(2024, 1, 1, 0, 0, 0),
239
+ RangeEnd = #datetime(2024, 12, 31, 23, 59, 59),
240
+
241
+ Source = Sql.Database("server", "database"),
242
+ Sales = Source{[Schema="dbo", Item="Sales"]}[Data],
243
+
244
+ // Date filter - required for incremental refresh
245
+ FilteredByDate = Table.SelectRows(Sales, each
246
+ [OrderDate] >= RangeStart and [OrderDate] < RangeEnd
247
+ )
248
+ in
249
+ FilteredByDate
250
+ ```
251
+
252
+ ---
253
+
254
+ ## Data Type Optimization
255
+
256
+ ### Set Types Early
257
+
258
+ ```m
259
+ let
260
+ Source = YourSource,
261
+
262
+ // Set types immediately after source
263
+ TypedTable = Table.TransformColumnTypes(Source, {
264
+ {"OrderID", Int64.Type},
265
+ {"CustomerID", Int64.Type},
266
+ {"Amount", Currency.Type},
267
+ {"OrderDate", type date},
268
+ {"CustomerName", type text}
269
+ })
270
+ in
271
+ TypedTable
272
+ ```
273
+
274
+ ### Avoid Implicit Type Conversion
275
+
276
+ ```m
277
+ let
278
+ Source = YourSource,
279
+
280
+ // BAD: Implicit conversion in comparison
281
+ BadFilter = Table.SelectRows(Source, each [Year] = "2024"), // Text comparison
282
+
283
+ // GOOD: Explicit types
284
+ GoodFilter = Table.SelectRows(Source, each [Year] = 2024) // Number comparison
285
+ in
286
+ GoodFilter
287
+ ```
288
+
289
+ ---
290
+
291
+ ## Reduce Query Dependencies
292
+
293
+ ### Avoid Circular References
294
+
295
+ ```m
296
+ // Separate staging and transformation queries
297
+
298
+ // Query: Sales_Staging (disable load)
299
+ let
300
+ Source = Sql.Database("server", "database"),
301
+ Sales = Source{[Schema="dbo", Item="Sales"]}[Data],
302
+ Typed = Table.TransformColumnTypes(Sales, {
303
+ {"Amount", type number},
304
+ {"Date", type date}
305
+ })
306
+ in
307
+ Typed
308
+
309
+ // Query: Sales_Fact (enable load)
310
+ let
311
+ Source = Sales_Staging, // Reference staging query
312
+ Filtered = Table.SelectRows(Source, each [Year] = 2024)
313
+ in
314
+ Filtered
315
+ ```
316
+
317
+ ### Use Parameters Instead of Queries
318
+
319
+ ```m
320
+ let
321
+ // Reference parameter instead of query
322
+ CurrentYear = CurrentYearParameter, // Defined as parameter
323
+
324
+ Source = Sql.Database("server", "database"),
325
+ Sales = Source{[Schema="dbo", Item="Sales"]}[Data],
326
+
327
+ Filtered = Table.SelectRows(Sales, each [Year] = CurrentYear)
328
+ in
329
+ Filtered
330
+ ```
331
+
332
+ ---
333
+
334
+ ## Native SQL When Needed
335
+
336
+ ### Use Value.NativeQuery
337
+
338
+ ```m
339
+ let
340
+ Source = Sql.Database("server", "database"),
341
+
342
+ // Complex query that's hard to fold
343
+ NativeQuery = Value.NativeQuery(
344
+ Source,
345
+ "SELECT
346
+ CustomerID,
347
+ SUM(Amount) as TotalAmount,
348
+ COUNT(*) as OrderCount
349
+ FROM Sales
350
+ WHERE Year = 2024
351
+ GROUP BY CustomerID
352
+ HAVING SUM(Amount) > 10000"
353
+ )
354
+ in
355
+ NativeQuery
356
+ ```
357
+
358
+ ### Parameterized Native Query
359
+
360
+ ```m
361
+ let
362
+ Source = Sql.Database("server", "database"),
363
+
364
+ // Using parameter to prevent SQL injection
365
+ YearValue = 2024,
366
+
367
+ Query = Value.NativeQuery(
368
+ Source,
369
+ "SELECT * FROM Sales WHERE Year = @year",
370
+ [year = YearValue]
371
+ )
372
+ in
373
+ Query
374
+ ```
375
+
376
+ ---
377
+
378
+ ## Memory Management
379
+
380
+ ### Avoid Large Lists in Memory
381
+
382
+ ```m
383
+ let
384
+ Source = YourSource,
385
+
386
+ // BAD: Creates large list in memory
387
+ BadPattern = List.Buffer(Table.Column(Source, "ID")),
388
+
389
+ // GOOD: Process without full materialization
390
+ GoodPattern = Table.SelectRows(Source, each [Status] = "Active")
391
+ in
392
+ GoodPattern
393
+ ```
394
+
395
+ ### Stream Processing
396
+
397
+ ```m
398
+ let
399
+ // For very large files, enable streaming
400
+ Source = Csv.Document(
401
+ File.Contents("C:\large_file.csv"),
402
+ [Delimiter=",", QuoteStyle=QuoteStyle.None]
403
+ ),
404
+
405
+ // First filter - reduces data in memory
406
+ Filtered = Table.SelectRows(Source, each [Status] = "Active"),
407
+
408
+ // Then type
409
+ Typed = Table.TransformColumnTypes(Filtered, {{"Amount", type number}})
410
+ in
411
+ Typed
412
+ ```
413
+
414
+ ---
415
+
416
+ ## Query Diagnostics
417
+
418
+ ### Enable Query Diagnostics
419
+
420
+ 1. Tools > Options > Diagnostics
421
+ 2. Enable "Query Diagnostics"
422
+ 3. Tools > Start Diagnostics
423
+ 4. Refresh query
424
+ 5. Tools > Stop Diagnostics
425
+ 6. Analyze the diagnostic tables
426
+
427
+ ### Key Metrics to Monitor
428
+
429
+ | Metric | Meaning |
430
+ |--------|---------|
431
+ | Duration | Total time for step |
432
+ | Row Count | Data volume |
433
+ | Data Source Query | Native query sent |
434
+ | Exclusive Duration | Time without dependencies |
435
+ | Resource | Which data source |
436
+
437
+ ---
438
+
439
+ ## Performance Checklist
440
+
441
+ ### Before Deploying
442
+
443
+ - [ ] Filter early in the query
444
+ - [ ] Select only needed columns
445
+ - [ ] Verify query folding (right-click > View Native Query)
446
+ - [ ] Set data types explicitly
447
+ - [ ] Remove or disable staging queries from load
448
+ - [ ] Check for unnecessary Table.Buffer calls
449
+ - [ ] Review query dependencies
450
+ - [ ] Test with production data volumes
451
+ - [ ] Enable query diagnostics for complex queries
452
+
453
+ ### Common Issues
454
+
455
+ | Symptom | Likely Cause | Fix |
456
+ |---------|--------------|-----|
457
+ | Slow refresh | Broken folding | Move filters up, simplify transforms |
458
+ | Memory errors | Large data in memory | Use Table.Buffer sparingly, filter early |
459
+ | Timeout | Complex query | Use native SQL, partition data |
460
+ | Slow step | Row-by-row processing | Use bulk operations |
461
+
462
+ ---
463
+
464
+ ## Folding Quick Reference
465
+
466
+ ### Functions That Typically Fold
467
+
468
+ ```
469
+ Table.SelectRows
470
+ Table.SelectColumns
471
+ Table.RemoveColumns
472
+ Table.Sort
473
+ Table.Group
474
+ Table.NestedJoin
475
+ Table.Distinct
476
+ Table.FirstN
477
+ Table.Skip
478
+ Table.TransformColumnTypes (basic types)
479
+ ```
480
+
481
+ ### Functions That Typically Break Folding
482
+
483
+ ```
484
+ Table.AddColumn (custom functions)
485
+ Table.Buffer
486
+ Table.FromList
487
+ Table.TransformColumns (complex transforms)
488
+ List.* functions in row context
489
+ Custom M functions
490
+ References to other queries
491
+ ```
492
+
493
+ ### Verify Folding
494
+
495
+ ```m
496
+ // Add this to see the native query
497
+ let
498
+ Source = Sql.Database("server", "database"),
499
+ Query = Source{[Schema="dbo", Item="Sales"]}[Data],
500
+ Filtered = Table.SelectRows(Query, each [Year] = 2024),
501
+
502
+ // This will show the SQL if folding works
503
+ NativeQuery = Value.NativeQuery(Source, "", [EnableFolding=true])
504
+ in
505
+ Filtered
506
+ ```