performance について
可視化を開発する人向けのデータクエリ最適化スキルです。必要な列だけを選び、行数を抑え、サーバー側でグループ化してデータ転送量を減らす方法を扱います。
主な機能
- 01データセット全体の取得を回避
- 02必要な列だけを選択
- 03サーバー側でのグループ化と集計
- 04可視化ごとに個別のクエリを実行
- 05転送量と応答時間の監視
活用シーン
- 01ダッシュボードの読み込みデータ量を削減
- 02個々のチャート用のクエリ結果を準備
- 03遅いクエリや過大なクエリの改善
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ stahura/ domo-ai-vibe-rules --skill performanceインストール後、Claude Code で/performanceを入力して読み込まれたか確認します。
詳細
パフォーマンス最適化 - 重要なベストプラクティス
データセット全体を取得しないでください
重要なルール: データセット全体、特に大規模なデータセット(10 万行以上)は絶対に取得しないでください。各ビジュアライゼーションに必要な列だけを使った、対象を絞ったクエリを常に使用してください。
パフォーマンスへの影響
// ❌ TERRIBLE - Fetches 300k rows × 30 columns = 9M data points
const allData = await new Query()
.select(['col1', 'col2', 'col3', ...]) // All columns
.fetch('dataset');
// ✅ GOOD - Fetches 300k rows × 2 columns = 600k data points (93% reduction)
const totals = await new Query()
.select(['Transactions', 'Total Amount (USD)'])
.fetch('dataset');
// Then aggregate client-side
// ✅ BEST - Server-side aggregation, returns only aggregated results
const totals = await new Query()
.groupBy('Merchant Category', { 'Total Amount (USD)': 'sum' })
.fetch('dataset');
// Returns only ~10-20 rows (one per category)
クエリ最適化戦略
1. 可能な場合はサーバーサイド集計を使用する
優先順位:
- 最適: 集計を伴う
.groupBy()(サーバーサイド) - 良好: 必要な列だけを指定する
.select()を使い、その後クライアントサイドで集計する - 許容可能: 集計できない場合に、複数の列を指定する
.select()を使う - 絶対に避ける: すべての列またはデータセット全体を取得する
// ✅ BEST - Server aggregates, returns minimal data
const salesByRegion = await new Query()
.groupBy('region', { 'Sales_Amount': 'sum', 'Order_Count': 'count' })
.fetch('sales');
// ✅ GOOD - Only fetch columns needed, aggregate client-side
const salesData = await new Query()
.select(['region', 'Sales_Amount'])
.fetch('sales');
const totalSales = salesData.reduce((sum, row) => sum + row.Sales_Amount, 0);
// ❌ BAD - Fetches all columns
const allData = await new Query().fetch('sales');
2. ビジュアライゼーションごとに 1 つのクエリを使用する
各ビジュアライゼーションには、最適化された専用のクエリを使用してください。
// ✅ CORRECT - Separate optimized queries
const quickStats = await fetchQuickStats(); // Only Account Key, Account Status
const riskMetrics = await fetchRiskMetrics(); // Only Transactions, KYC Status, etc.
const categories = await fetchCategories(); // Grouped by Merchant Category
// ❌ WRONG - One query for everything
const allData = await fetchAllData();
const quickStats = calculateFromAll(allData);
const riskMetrics = calculateFromAll(allData);
const categories = calculateFromAll(allData);
3. 列の選択戦略
列は必ず明示的に指定してください:
- 特定の計算に必要な列だけを選択する
- 引数なしで
.select()を使わない(すべての列が取得されます) - 集計では、グループ化列と集計対象の列だけを選択する
// ✅ CORRECT - Only 2 columns
const data = await new Query()
.select(['Account Key', 'Account Status'])
.fetch('dataset');
// ❌ WRONG - Fetches all columns
const data = await new Query().fetch('dataset');
よくあるパターン
パターン 1:グループ化しない合計値
グループ化列なしで合計値が必要な場合:
// Option A: Select only needed columns, sum client-side
const totalsData = await new Query()
.select(['Transactions', 'Total Amount (USD)'])
.fetch('dataset');
const totalTransactions = totalsData.reduce((sum, row) => sum + (row.Transactions || 0), 0);
const totalVolume = totalsData.reduce((sum, row) => sum + (row['Total Amount (USD)'] || 0), 0);
// Option B: Use a constant grouping column (if dataset has one)
// Not always possible, but more efficient if available
パターン 2:フィルターを使ったカウント
// ✅ CORRECT - Only fetch the column needed for counting
const kycData = await new Query()
.select(['KYC Status'])
.fetch('dataset');
const approvedCount = kycData.filter(row => row['KYC Status'] === 'APPROVED').length;
// Better if possible: Use server-side count aggregation
// (See Query API limitations below)
パターン 3:一意の値
// ✅ CORRECT - Only fetch the column needed
const statesData = await new Query()
.select(['State'])
.fetch('dataset');
const uniqueStates = new Set(statesData.map(row => row.State)).size;
クエリ API の制限事項
.aggregate() は動作しません
重要: 一部のドキュメントに記載されている .aggregate() メソッドは、実際には動作しません。次のエラーが発生します:DA0057: An alias list was provided but it could not be parsed。
// ❌ DOES NOT WORK - Causes DA0057 error
const totals = await new Query()
.aggregate({ 'Transactions': 'sum', 'Total Amount (USD)': 'sum' })
.fetch('dataset');
// ✅ WORKAROUND - Use .groupBy() with a grouping column
const totals = await new Query()
.groupBy('some_column', { 'Transactions': 'sum', 'Total Amount (USD)': 'sum' })
.fetch('dataset');
// ✅ ALTERNATIVE - Select columns and aggregate client-side
const totals = await new Query()
.select(['Transactions', 'Total Amount (USD)'])
.fetch('dataset');
// Then sum client-side
.groupBy() にはグループ化列が必要です
集計だけで .groupBy() を使うことはできません。グループ化列を指定する必要があります。
// ❌ DOES NOT WORK - No grouping column
.groupBy({ 'Transactions': 'sum' })
// ✅ WORKS - Has grouping column
.groupBy('region', { 'Transactions': 'sum' })
// ✅ WORKS - Multiple groupBy calls
.groupBy('region')
.groupBy({ 'Transactions': 'sum' })
パフォーマンスの監視
次の項目を常に確認してください。
- ネットワークタブ - 転送されているデータ量はどのくらいですか?
- コンソール - 大規模なクエリに関する警告はありますか?
- 応答時間 - クエリに時間がかかりすぎていませんか?
クエリの実行が遅い場合や、データが多すぎる場合:
- 選択する列を減らす
- フィルターを追加して行数を減らす
- クライアントサイドではなく、サーバーサイドの集計を使用する
- 大規模な結果セットにはページネーションを検討する
コメント
Markdown 対応