メインコンテンツまでスキップ

第 6 回:もっと便利に!Neo4j Workspace の便利な小技集

実体験から学ぶ:パフォーマンス問題との遭遇

あるプロジェクトで、データ量が増加するにつれてクエリの実行時間が徐々に長くなり、最終的には数分かかるようになってしまいました。PROFILE 機能を使って実行計画を分析したところ、インデックスの不足が原因であることが判明し、適切なインデックス追加により実行時間を 95%削減できました。

スキーマ可視化による構造把握

CALL db.schema.visualization()の実践活用

データベースの全体構造を理解することは、効率的なクエリ開発の前提条件です。

Schema Visualization

基本的な実行方法:

CALL db.schema.visualization()

私の実践的な活用方法:

新規プロジェクト参加時の理解促進

1. スキーマ全体の把握
2. 主要なエンティティの特定
3. 関係性の複雑度評価
4. データモデルの妥当性確認

データモデル設計の品質評価

評価観点:
□ ノードラベルの命名一貫性
□ リレーションシップの論理的妥当性
□ エンティティ間の結合度
□ 正規化レベルの適切性

スキーマ情報の詳細分析

より詳細な構造分析には、追加的なクエリが有効です。

Detailed Schema Analysis

詳細分析クエリ例:

// ノードラベル別の詳細統計
MATCH (n)
RETURN labels(n) as NodeLabels,
count(n) as NodeCount,
avg(size(keys(n))) as AvgProperties
ORDER BY NodeCount DESC

// リレーションシップタイプ別の統計
MATCH ()-[r]->()
RETURN type(r) as RelType,
count(r) as RelCount,
avg(size(keys(r))) as AvgRelProperties
ORDER BY RelCount DESC

// データモデルの複雑度分析
MATCH (n)-[r]->()
WITH labels(n) as FromLabel, type(r) as RelType,
count(*) as Frequency
RETURN FromLabel, RelType, Frequency
ORDER BY Frequency DESC

Saved Cypher によるクエリ管理

効率的なクエリライブラリの構築

実際のプロジェクトでは、再利用可能なクエリコレクションの構築が生産性向上の鍵となります。

Saved Cypher Organization

私のクエリ分類システム:

カテゴリ別クエリ管理

📁 Daily Analytics/
- Node Count Check
- Relationship Count Check
- Data Growth Monitor

📁 Data Quality/
- Orphaned Nodes Detection
- Duplicate Check
- Missing Properties

📁 Business Reports/
- Monthly Revenue Analysis
- Team Performance Metrics
- Customer Network Analysis

📁 Debug Queries/
- Performance Test Queries
- Schema Validation
- Connection Test

命名規則の確立

形式: [カテゴリ]_[対象]_[目的]_[更新日]
例:
- DAILY_nodes_count_20240701
- QUALITY_employees_duplicate_check
- BUSINESS_revenue_monthly_analysis
- DEBUG_performance_index_test

クエリテンプレートの作成

頻繁に使用するパターンは、パラメータ化されたテンプレートとして保存します。

実際のテンプレート例:

// 企業分析テンプレート
MATCH (company:Company {name: $companyName})
OPTIONAL MATCH (company)-[EMPLOYS]->(emp:Employee)
OPTIONAL MATCH (emp)-[WORKS_ON]->(proj:Project)
RETURN company,
count(DISTINCT emp) as EmployeeCount,
count(DISTINCT proj) as ProjectCount,
collect(DISTINCT emp.department) as Departments
// 期間別分析テンプレート
MATCH (proj:Project)
WHERE proj.start_date >= date($startDate)
AND proj.start_date <= date($endDate)
MATCH (proj)<-[WORKS_ON]-(emp:Employee)
RETURN proj.name as Project,
proj.budget as Budget,
count(emp) as TeamSize,
(proj.budget / count(emp)) as BudgetPerPerson
ORDER BY Budget DESC

パフォーマンス分析と最適化

EXPLAIN vs PROFILE の使い分け

クエリの性能問題を解決するには、実行計画の理解が不可欠です。

Explain vs Profile

EXPLAIN:事前分析用

EXPLAIN
MATCH (emp:Employee {department: $dept})
-[WORKS_ON]->(proj:Project)
WHERE proj.budget > $minBudget
RETURN emp, proj

用途:

  • クエリ実行前の計画確認
  • 大量データでの事前検証
  • インデックス使用状況の確認

PROFILE:実績分析用

PROFILE
MATCH (emp:Employee {department: $dept})
-[WORKS_ON]->(proj:Project)
WHERE proj.budget > $minBudget
RETURN emp, proj

用途:

  • 実際のパフォーマンス測定
  • ボトルネック箇所の特定
  • 最適化効果の定量評価

実際のパフォーマンス最適化事例

私が遭遇した典型的な問題と解決策:

問題 1:全ノードスキャンの発生

// 最適化前(遅い)
MATCH (emp:Employee)
WHERE emp.email = 'john@company.com'
RETURN emp

// 実行計画で発見された問題:
// NodeByLabelScan (Employee) - 全Employeeノードをスキャン

解決策:インデックス作成

// インデックス作成
CREATE INDEX FOR (e:Employee) ON (e.email)

// 最適化後の実行計画:
// NodeIndexSeek (Employee.email) - インデックス使用

問題 2:非効率な JOIN パターン

// 最適化前
MATCH (emp:Employee)-[WORKS_ON]->(proj:Project)
MATCH (emp)-[EMPLOYS]->(company:Company) // 逆方向
WHERE company.name = $companyName
RETURN emp, proj

// 最適化後
MATCH (company:Company {name: $companyName})
-[EMPLOYS]->(emp:Employee)
-[WORKS_ON]->(proj:Project)
RETURN emp, proj

改善効果:

  • 実行時間:15 秒 → 0.3 秒(95%削減)
  • DB Hits:150,000 → 3,000(98%削減)

パラメータの効果的な活用

UI でのパラメータ設定

動的なクエリ実行には、パラメータの活用が重要です。

Parameter Configuration

実際の設定例:

GUI での設定手順

1. Workspaceでパラメータパネル({}アイコン)を開く
2. パラメータ名と値を入力:
companyName: "TechCorp Inc"
startDate: "2024-01-01"
minBudget: 1000000
3. "Apply Parameters"をクリック

:param コマンドでの設定

:param companyName => 'TechCorp Inc'
:param startDate => '2024-01-01'
:param minBudget => 1000000

パラメータ化による再利用性向上

実際のプロジェクトでの活用例:

// 柔軟な企業分析クエリ
MATCH (company:Company)
WHERE ($companyName IS NULL OR company.name = $companyName)
AND ($industry IS NULL OR company.industry = $industry)
AND ($minSize IS NULL OR company.size >= $minSize)

OPTIONAL MATCH (company)-[EMPLOYS]->(emp:Employee)
WHERE ($department IS NULL OR emp.department = $department)

OPTIONAL MATCH (emp)-[WORKS_ON]->(proj:Project)
WHERE ($projectStatus IS NULL OR proj.status = $projectStatus)
AND ($minBudget IS NULL OR proj.budget >= $minBudget)

RETURN company.name as Company,
company.industry as Industry,
count(DISTINCT emp) as EmployeeCount,
count(DISTINCT proj) as ProjectCount,
sum(proj.budget) as TotalBudget
ORDER BY TotalBudget DESC

メリット:

  • セキュリティ: SQL インジェクション対策
  • パフォーマンス: 実行計画のキャッシュ効果
  • 再利用性: 同一クエリで異なる条件指定
  • 保守性: ハードコーディングの排除

高度なデバッグテクニック

データ品質チェッククエリ集

実際のプロジェクトで蓄積した、データ品質確認用クエリをご紹介します。

Data Quality Dashboard

基本的な整合性チェック

// 1. 孤立ノード(関係性のないノード)の検出
MATCH (n)
WHERE NOT (n)--()
RETURN labels(n) as NodeType, count(n) as OrphanCount
ORDER BY OrphanCount DESC

// 2. 重複の可能性があるノード
MATCH (n:Employee)
WITH n.email as email, collect(n) as nodes
WHERE size(nodes) > 1
RETURN email, size(nodes) as DuplicateCount

// 3. 必須プロパティの欠損
MATCH (c:Company)
WHERE c.name IS NULL OR c.industry IS NULL
RETURN count(c) as CompaniesWithMissingData

// 4. 不正な関係性
MATCH (emp:Employee)-[EMPLOYS]->(company:Company)
RETURN count(*) as IncorrectRelationshipDirection

ビジネスルール違反の検出

// 1. 入社日が会社設立日より前の社員
MATCH (company:Company)<-[EMPLOYS]-(emp:Employee)
WHERE emp.start_date < date(company.founded_year + '-01-01')
RETURN company.name, emp.name, emp.start_date, company.founded_year

// 2. 予算がマイナスのプロジェクト
MATCH (proj:Project)
WHERE proj.budget < 0
RETURN proj.name, proj.budget

// 3. 管理者が存在しないプロジェクト
MATCH (proj:Project)
WHERE NOT (proj)<-[MANAGES]-(:Employee)
RETURN proj.name as UnmanagedProject

システム状態の監視

運用環境での重要な監視クエリ:

// データベース統計の取得
CALL db.stats.retrieve('GRAPH COUNTS')
YIELD section, data
RETURN section, data

// インデックス使用状況
CALL db.indexes()
YIELD name, labelsOrTypes, properties, state, populationPercent
RETURN name, labelsOrTypes, properties, state, populationPercent
ORDER BY populationPercent DESC

// 制約の確認
CALL db.constraints()
YIELD name, description, type
RETURN name, description, type

実践的なワークフロー最適化

日常業務での効率化テクニック

実際のプロジェクトで確立した、生産性向上のワークフローをご紹介します。

Workflow Optimization

朝の確認ルーチン(5 分)

// 1. システム正常性確認
:play system-check

// 2. データ更新状況確認
MATCH (n)
WHERE n.updated_at >= date() - duration({days: 1})
RETURN labels(n), count(n)

// 3. 昨日の作業継続用クエリをSaved Cypherから実行

開発作業での効率化

□ パラメータパネルの事前設定
□ よく使うクエリのSaved Cypher登録
□ EXPLAINでの事前性能確認
□ 段階的なクエリ作成(小→大)

終了時の整理作業

□ 有用なクエリのSaved Cypher保存
□ パフォーマンス問題の記録
□ 翌日用パラメータの準備
□ 作業ログの更新

トラブルシューティング集

よくある問題と解決策

実際のプロジェクトで遭遇した問題をまとめました。

問題 1:Saved Cypher が消失

原因: ブラウザキャッシュクリア 解決策:

  • 定期的なエクスポート実行
  • 重要なクエリの別途バックアップ
  • チーム共有での冗長性確保

問題 2:パラメータが認識されない

原因: パラメータ名の typo、データ型不一致 解決策:

// パラメータ確認コマンド
:params

// 正しい設定例
:param companyName => 'TechCorp Inc' // 文字列
:param minBudget => 1000000 // 数値
:param startDate => date('2024-01-01') // 日付

問題 3:実行計画が読めない

解決策:

  • 基本パターンの習得(Scan → Filter → Return)
  • ボトルネック箇所の特定(高い DB Hits)
  • インデックス効果の確認(Seek vs Scan)

次のステップ:チーム運用への準備

Workspace の高度な機能をマスターしたら、次はチーム開発とセキュリティ管理について学習しましょう。

第 7 回では以下を扱います:

  • ユーザー管理とアクセス制御
  • チーム開発のベストプラクティス
  • バックアップとリストア戦略

実践のまとめ:

  1. スキーマ可視化による構造理解の促進
  2. Saved Cypher による効率的なクエリ管理
  3. EXPLAIN/PROFILE によるパフォーマンス最適化
  4. パラメータ化による再利用性とセキュリティ向上

次回: 第 7 回:チーム開発とセキュリティの第一歩


著者: hnish - walk-with-ai AI/DX コンサルタント
最終更新: 2025 年 7 月 1 日