2026年版 LookerとLookML完全ガイド:ビジネスインテリジェンスと面接対策

LookMLのセマンティックレイヤー、データモデリング、実践的な実装パターンを解説。2026年のデータアナリスト面接で頻出するLooker関連の質問と回答例を網羅したチュートリアル。

Looker and LookML Business Intelligence Interview Guide

Lookerの面接では、LookMLモデリング、データ探索ワークフロー、そしてセマンティックレイヤーがビジネスロジックを再利用可能な定義に変換する仕組みが問われます。本チュートリアルでは、LookMLの核となる概念、実践的な実装パターン、そして2026年にLooker関連のポジションで面接を受けるデータアナリストが直面する具体的な質問を解説します。

LookMLの重要概念

LookMLはデータモデリングとデータ探索を分離します。アナリストがモデルレイヤーでディメンション、メジャー、リレーションシップを一度定義すれば、ビジネスユーザーはSQLを書かずにデータをクエリできます。この設計パターンは、Lookerの技術面接でほぼ必ず登場します。

LookMLセマンティックレイヤーの理解

LookMLは、生のデータベーステーブルとビジネスフレンドリーな指標の間の変換レイヤーとして機能します。複雑なSQL結合を何度も記述する代わりに、アナリストはモデルファイルでリレーションシップを定義し、Lookerがそれを最適化されたクエリにコンパイルします。

セマンティックレイヤーは、面接官が頻繁に質問する3つの問題を解決します:

  • 一貫性:すべてのユーザーが同じ指標定義を参照できる
  • 再利用性:ディメンションとメジャーは一度定義すれば、どこからでも参照可能
  • ガバナンス:変更はすべてのダッシュボードに自動的に反映される

Google CloudのLookerドキュメントでは、LookMLを「依存関係を認識する」言語として説明しています。ある定義が変更されると、下流の参照が自動的に更新されます。この依存関係の認識機能は、エンタープライズ規模のモデルを維持する際に極めて重要になります。

LookMLのViewとExplore:基本構成要素

Viewは単一のテーブルまたは派生テーブルから利用可能なカラムを定義します。ExploreはViewを結合して組み合わせ、ビジネスユーザーに公開します。

lookml
# views/orders.view.lkml
view: orders {
  sql_table_name: `analytics.orders` ;;

  dimension: order_id {
    primary_key: yes
    type: number
    sql: ${TABLE}.order_id ;;
  }

  dimension_group: created {
    type: time
    timeframes: [raw, date, week, month, quarter, year]
    sql: ${TABLE}.created_at ;;
  }

  dimension: status {
    type: string
    sql: ${TABLE}.status ;;
  }

  measure: total_orders {
    type: count
    drill_fields: [order_id, created_date, status]
  }

  measure: total_revenue {
    type: sum
    sql: ${TABLE}.amount ;;
    value_format_name: usd
  }
}

dimension_group宣言は、単一のタイムスタンプカラムから複数の時間ベースのディメンションを生成します。面接官はしばしば、このパターンがコードの重複を減らし、モデル全体で一貫した日付処理を保証する理由を説明するよう候補者に求めます。

drill_fieldsパラメータは、ユーザーがメジャー値をクリックしたときに表示される内容を定義します。これはアナリストが実際にLookerとどのようにやり取りするかを示すUXの詳細であり、理解度を測る重要なポイントです。

LookMLにおける結合とリレーションシップ

Exploreは、ViewがSQL結合を通じてどのように接続されるかを定義します。結合タイプとリレーションシップ宣言は、クエリパフォーマンスと集計の精度に直接影響を与えます。

lookml
# models/ecommerce.model.lkml
explore: orders {
  label: "注文分析"
  description: "注文、顧客、商品データを結合した分析用Explore"

  join: customers {
    type: left_outer
    relationship: many_to_one
    sql_on: ${orders.customer_id} = ${customers.customer_id} ;;
  }

  join: products {
    type: left_outer
    relationship: many_to_one
    sql_on: ${orders.product_id} = ${products.product_id} ;;
  }

  join: order_items {
    type: left_outer
    relationship: one_to_many
    sql_on: ${orders.order_id} = ${order_items.order_id} ;;
  }
}

relationshipパラメータは、Lookerにファンアウト問題を正しく処理する方法を伝えます。one_to_manyの結合でメジャーを集計する際、Lookerは対称集計を適用して正確な結果を保証します。

面接での頻出質問:ファンアウト問題

面接官は定期的に候補者にファンアウト問題の説明を求めます。注文に複数の商品がある場合、単純なSUM集計は各商品行で注文合計を二重にカウントします。Lookerの対称集計がこれを自動的に処理しますが、候補者は基礎となるSQL変換を説明できる必要があります。

sql
-- Lookerが生成する対称集計SQL
SELECT
  SUM(DISTINCT CONCAT(
    CAST(orders.order_id AS STRING),
    '|',
    CAST(orders.amount AS STRING)
  )) AS total_revenue
FROM orders
JOIN order_items ON orders.order_id = order_items.order_id

派生テーブルとPDT(永続的派生テーブル)

派生テーブルは、SQLクエリまたはネイティブLookMLから動的に計算されたテーブルを作成します。永続的派生テーブル(PDT)はこれらの結果をデータベースにキャッシュしてパフォーマンスを向上させます。

lookml
view: daily_order_summary {
  derived_table: {
    sql:
      SELECT
        DATE(created_at) AS order_date,
        COUNT(*) AS order_count,
        SUM(amount) AS daily_revenue
      FROM orders
      GROUP BY 1
    ;;

    datagroup_trigger: orders_datagroup
    indexes: ["order_date"]
  }

  dimension: order_date {
    type: date
    sql: ${TABLE}.order_date ;;
  }

  measure: total_order_count {
    type: sum
    sql: ${TABLE}.order_count ;;
  }

  measure: total_daily_revenue {
    type: sum
    sql: ${TABLE}.daily_revenue ;;
  }
}

datagroup_triggerパラメータは、PDTがいつ再構築されるかを制御します。データグループはデータの鮮度を定義し、複数のPDTで再利用できるため、ウェアハウスコストを削減しながら一貫した更新を確保できます。

ネイティブ派生テーブル

ネイティブ派生テーブルは生のSQLの代わりにLookML構文を使用し、既存のディメンションとメジャーを活用できます。

lookml
view: customer_lifetime_value {
  derived_table: {
    explore_source: orders {
      column: customer_id { field: customers.customer_id }
      column: total_orders { field: orders.total_orders }
      column: total_revenue { field: orders.total_revenue }
      column: first_order_date { field: orders.created_date }
      column: last_order_date { field: orders.created_date }

      derived_column: customer_tenure_days {
        sql: DATE_DIFF(last_order_date, first_order_date, DAY) ;;
      }
    }

    datagroup_trigger: orders_datagroup
  }

  dimension: customer_id {
    primary_key: yes
    type: number
  }

  dimension: customer_segment {
    type: string
    sql:
      CASE
        WHEN ${total_revenue} >= 10000 THEN 'VIP'
        WHEN ${total_revenue} >= 1000 THEN 'Active'
        ELSE 'Standard'
      END
    ;;
  }
}

Looker面接で頻出する技術的質問

質問1:LiquidテンプレートとLookML

LiquidはLookML内でパラメータ化されたSQL、動的なフィールド可視性、コンテキスト依存のロジックを可能にします。

lookml
view: orders {
  parameter: date_granularity {
    type: unquoted
    allowed_values: ["day", "week", "month", "quarter", "year"]
    default_value: "month"
  }

  dimension: dynamic_date {
    type: string
    sql:
      {% if date_granularity._parameter_value == 'day' %}
        DATE(${created_raw})
      {% elsif date_granularity._parameter_value == 'week' %}
        DATE_TRUNC(${created_raw}, WEEK)
      {% elsif date_granularity._parameter_value == 'month' %}
        DATE_TRUNC(${created_raw}, MONTH)
      {% elsif date_granularity._parameter_value == 'quarter' %}
        DATE_TRUNC(${created_raw}, QUARTER)
      {% else %}
        DATE_TRUNC(${created_raw}, YEAR)
      {% endif %}
    ;;
  }

  measure: filtered_revenue {
    type: sum
    sql: ${TABLE}.amount ;;
    filters: [status: "completed, shipped"]
  }
}

質問2:アクセスフィルターと行レベルセキュリティ

面接官は候補者に、機密データをどのように保護しながら適切なアクセスを許可するかを説明するよう求めます。

lookml
explore: orders {
  access_filter: {
    field: orders.region
    user_attribute: allowed_regions
  }

  access_filter: {
    field: customers.customer_segment
    user_attribute: visible_segments
  }
}

アクセスフィルターは、行レベルのセキュリティを自動的に適用します。ユーザー属性に基づいてデータが自動的にフィルタリングされ、手動のWHERE句を必要としません。

質問3:キャッシュ戦略とデータグループ

効率的なキャッシュ戦略は、ユーザーエクスペリエンスとデータベースコストの両方に影響を与えます。

lookml
datagroup: orders_datagroup {
  max_cache_age: "24 hours"
  sql_trigger: SELECT MAX(updated_at) FROM orders ;;
}

datagroup: realtime_datagroup {
  max_cache_age: "5 minutes"
  sql_trigger: SELECT CURRENT_TIMESTAMP() ;;
}

explore: orders {
  persist_with: orders_datagroup
}

explore: realtime_metrics {
  persist_with: realtime_datagroup
}

Data Analyticsの面接対策はできていますか?

インタラクティブなシミュレーター、flashcards、技術テストで練習しましょう。

パフォーマンス最適化テクニック

集計認識

集計認識により、Lookerはクエリ要件に基づいて詳細テーブルと集計テーブルのどちらから読み取るかを自動的に選択できます。

lookml
explore: orders {
  aggregate_table: daily_orders_rollup {
    query: {
      dimensions: [created_date, status, region]
      measures: [total_orders, total_revenue]
    }

    materialization: {
      datagroup_trigger: orders_datagroup
    }
  }

  aggregate_table: monthly_orders_rollup {
    query: {
      dimensions: [created_month, status]
      measures: [total_orders, total_revenue, average_order_value]
    }

    materialization: {
      datagroup_trigger: orders_datagroup
    }
  }
}

インクリメンタルPDT

大規模なデータセットの場合、インクリメンタルPDTはフルテーブルスキャンを回避して新しいレコードのみを追加します。

lookml
view: incremental_orders {
  derived_table: {
    sql:
      SELECT *
      FROM orders
      WHERE created_at >= COALESCE(
        (SELECT MAX(created_at) FROM ${SQL_TABLE_NAME}),
        '1900-01-01'
      )
    ;;

    datagroup_trigger: hourly_datagroup
    increment_key: "created_at"
    increment_offset: 3
  }
}

Looker APIとシステム統合

LookerのAPIは、自動化、埋め込み、外部システムとの統合を可能にします。

python
import looker_sdk

sdk = looker_sdk.init40()

# ダッシュボードをプログラムで実行
result = sdk.run_look(
    look_id=123,
    result_format="json"
)

# スケジュールを動的に作成
schedule = sdk.create_scheduled_plan(
    body={
        "name": "Daily Revenue Report",
        "look_id": 123,
        "crontab": "0 9 * * *",
        "scheduled_plan_destination": [{
            "type": "email",
            "address": "analytics@company.com",
            "format": "csv"
        }]
    }
)

# モデル検証を自動化
validation = sdk.validate_project(
    project_id="my_project"
)

if validation.errors:
    for error in validation.errors:
        print(f"Error in {error.file_path}: {error.message}")

面接成功のためのベストプラクティス

モデル構成

大規模なLookMLプロジェクトでは、明確なファイル構成が保守性の鍵となります。

text
models/
├── ecommerce.model.lkml
├── marketing.model.lkml
└── finance.model.lkml

views/
├── core/
│   ├── orders.view.lkml
│   ├── customers.view.lkml
│   └── products.view.lkml
├── derived/
│   ├── customer_ltv.view.lkml
│   └── daily_metrics.view.lkml
└── extensions/
    └── order_extended.view.lkml

datagroups/
└── datagroups.lkml

命名規則

一貫した命名規則により、チーム全体でコードの可読性が向上します。

  • ディメンション:スネークケースで名詞を使用(例:customer_id, order_status
  • メジャー:プレフィックスで集計タイプを示す(例:total_revenue, count_orders, avg_order_value
  • Explore:分析対象を明確に表現(例:order_analysis, customer_behavior

結論

LookerとLookMLは、現代のビジネスインテリジェンススタックにおいて重要な役割を果たしています。面接では、セマンティックレイヤーの概念的理解だけでなく、パフォーマンス最適化、セキュリティ実装、そして実際のビジネス課題を解決するためのモデリング能力が問われます。

本チュートリアルで解説したLookMLの基本構文、結合とリレーションシップの設計、派生テーブル、Liquid構文、そしてキャッシュ戦略は、データアナリストのLooker面接で最も頻出するトピックです。これらの概念を実際のプロジェクトで適用し、実践的な経験を積むことが、面接成功への最善の準備となります。

タグ

#looker
#lookml
#business-intelligence
#data-analytics
#interview

共有

関連記事