はじめに
DataBricksは、巨大データの収集整理からAIによる解析までドカンと一気通貫で行える統合プラットフォーム…いわばデータの巨大ショッピングモールです(雑)。
位置データに関しては、億単位の地物や移動体データもとに物流ルートの最適化や店舗戦略予測などなどが可能とされており、最新のMosaic AIのサポートで自然言語での分析やAI構築の自動化が加速しています。
これらはDataSharingというオープンな規格で様々なツールやアプリケーションへの接続が可能なため、ベンダーロックインのリスクを下げ、データの民主化と意思決定を迅速化するとされています。詳しくはこちらなどを御覧ください
さて先日某MTGで「DataBricksとかどうすか?」と話題に上がった際、そういえば気にしていたもののあまり触っていたこともあり、まずはQGISからどのようにアプローチできるか検証を行いました。
なお、数カ月まえからスキマ時間に検証を行っていたところ、Databricks DBSQL Connectorというプラグインが最近ローンチされたので「あーハイ、そうですか、ワイの検証も終了かあ」と思いつつ試してみたのですが、このQiitaを書いているときのv1.0ではまず、urllib3が.1.25以下だとプラグインが起動しません(最新版QGISなら1.25以上なのでおそらく大丈夫)。また、DataBricksへの接続時にユーザーアカウントの全てのカタログ・スキーマ・テーブルを確認するようで、大きめのデータを扱う際なかなか接続できないという状況にありました。
わたしの設定やアプローチがおかしいのかもしれませんが、このプラグインはDataBricks側である程度ミニマムなデータに加工してから、QGISで読むには良いのかもしれません。しかし今後バージョンアップでさらに使いやすくなるかもしれないので、期待大ですね。
そのため、現状ではやや回り道かもしれませんが、
- DataBricks謹製のdatabricks-sql-connectorライブラリをQGISに追加
- QGISからOverTure Mapsのデータに関するリクエストをDatabricksに送る
- その結果をQGISで見る
ということをやってみます。なお、🤖とケンカしながら試行錯誤して検証しているところもありますので、ご了承くださいませ
また、QGISにdatabricks-sql-connectorライブラリのインストールを行いますので、At your risk でお試しください。
環境はMacOSのQGIS3.44.6-Solothurnで、筆者はビリヤニが好きです。
事前準備
まずDataBricksのwebページから各種事前準備を行います。
DataBricksのフリートライアルでサインアップをします。サインアップから14日間は無料で利用することが可能ですし、登録時に恐怖のキャッシュカード登録が不要なのはありがたいです。
なお、この手引きでは、右上のユーザーアイコン→環境設定→言語「日本語」での表示で説明します。
接続情報の取得
QGISからの接続には、DataBricksの
- ホスト名
- HTTPパス
- トークン
情報が必要になります。
この手順にしたがって、「接続の詳細」をみクリックすると、サーバーのホスト名およびHTTPパスが確認できます。←のコピーボタンを押して、どこぞにメモしておきましょう
トークンはこちらの手順に従って取得してください。
なお、新規トークン生成時の一度しかトークンは表示されないのでご注意を

これで、三種の神器が揃いました。
サンプルデータの登録
次に、今回はDataBricksにバンドルされている世界の超弩級地図データOverture Mapsの「Place」データを用います。このレコードは5400万件ほどあり、ライセンスはおもにユルめのCDLA Permissive 2.0です。
アカウントのワークスペースに登録するために、左のMarketPlace→🔎overture maps→Overture Maps - Placesをクリック
利用規約を確認の上、右上の「即時アクセス権を取得」をもう一度クリック
左メニューの「カタログ」にcarto_overture_maps_placesが追加されていればOKです。これで旅の準備が完了です。
QGISとの接続
databricks-sql-connectorのインストール
それでは、DataBricksと接続するためのPythonライブラリである、databricks-sql-connectorをインストールします。
GISのPythonコンソールで以下を実行してください。実行後、ライブラリを反映させるためにQGISを再起動してください。
from pip._internal import main as pip_main
pip_main(['install', '--user', 'databricks-sql-connector'])
接続確認
では上記で得た三種の神器
- ホスト名
- HTTPパス
- トークン
を下記コード上に入れ替え、QGISのPythonコンソールで実行してください。
from databricks import sql
HOSTNAME="XXXXXXXXXX.cloud.databricks.com"
HTTP_PATH="/sql/1.0/warehouses/XXXXXXXXXXXXXXXXXX"
TOKEN="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
# Shinjuku Sta
LON0, LAT0 = 139.7006, 35.6896
Q = f"""
WITH p AS (
SELECT
names.primary AS name,
CAST((bbox.xmin + bbox.xmax)/2 AS DOUBLE) AS lon,
CAST((bbox.ymin + bbox.ymax)/2 AS DOUBLE) AS lat
FROM place
WHERE names.primary IS NOT NULL AND bbox IS NOT NULL
),
r AS (
SELECT
name, lon, lat,
SQRT(POWER(lon - {LON0}, 2) + POWER(lat - {LAT0}, 2)) AS d
FROM p
WHERE lon BETWEEN {LON0}-0.05 AND {LON0}+0.05
AND lat BETWEEN {LAT0}-0.05 AND {LAT0}+0.05
)
SELECT name, lon, lat, d
FROM r
ORDER BY d
LIMIT 10
"""
with sql.connect(server_hostname=HOSTNAME, http_path=HTTP_PATH, access_token=TOKEN) as c, c.cursor() as cur:
cur.execute("USE CATALOG `carto_overture_maps_places`"); cur.execute("USE SCHEMA `carto`")
cur.execute(Q)
print("name\tlon\tlat\td")
for name, lon, lat, d in cur.fetchall():
print(f"{name}\t{lon:.6f}\t{lat:.6f}\t{d:.6f}")
データのバージョンなどによって多少異なるかもしれませんが、新宿駅(139.7006, 35.6896)周辺のPOI10件と距離が抽出されます。
name lon lat d
Public Tokyo Mens 139.700623 35.689613 0.000026
A+Tokyo Mens 139.700623 35.689613 0.000026
Plaza ルミネ新宿 139.700592 35.689644 0.000045
ネイルステーション 139.700592 35.689651 0.000052
NewDays 139.700653 35.689613 0.000055
United Tokyo Mens Shinjuku 139.700623 35.689659 0.000063
SNIDEL Lumine Shinjuku 2 139.700623 35.689667 0.000070
Lacoste 139.700623 35.689671 0.000074
Maison de Fleur 139.700623 35.689674 0.000078
Maison Special Mens 139.700623 35.689674 0.000078
databricks-sql-connectorのアンインストール
万が一databricks-sql-connectorによる不具合が疑われる場合は、QGISのPythonコンソールでアンインストールが可能です
from pip._internal import main as pip_main
pip_main(["uninstall", "-y", "databricks-sql-connector"])
QGISからリクエストを投げる
ではこれでDataBricksのデータ資源がQGISから読み込めます。もうFTPから巨大ZIPのダウンロードして解凍()して属性テーブルで検索するなんで手間からおさらばです。
たとえば、DataBricksに東京都23区の区域内におけるPlaceがあるデータをH3Indexの解像度9で集計してというSQLを投げて、QGISで表示させるコードはこんな感じになります。
私の環境(Macbook Air M4 2025 32GB)だと8秒ほどで処理が終わりました。
import time
from databricks import sql
from qgis.core import (
QgsVectorLayer, QgsProject, QgsFeature, QgsGeometry, QgsField,
QgsGraduatedSymbolRenderer, QgsRendererRange, QgsSymbol, QgsStyle
)
from qgis.PyQt.QtCore import QVariant
from qgis.PyQt.QtGui import QColor
T_ALL = time.perf_counter()
# ============================================================
# Databricks 接続
# ============================================================
HOSTNAME = "XXXXXXXXXXXXXXXXXXXX.cloud.databricks.com"
HTTP_PATH = "/sql/1.0/warehouses/XXXXXXXXXXXXXXXXXXXX"
TOKEN = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
CATALOG = "carto_overture_maps_places"
SCHEMA = "carto"
# ============================================================
# 検索・処理パラメータ
# ============================================================
H3_RES = 9
LIMIT_N = 20000
# 東京23区 bbox
LON_MIN, LON_MAX = 139.56, 139.92
LAT_MIN, LAT_MAX = 35.53, 35.82
# ============================================================
# SQL
# ============================================================
QUERY = f"""
WITH base AS (
SELECT
CAST((bbox.xmin + bbox.xmax)/2 AS DOUBLE) AS lon,
CAST((bbox.ymin + bbox.ymax)/2 AS DOUBLE) AS lat
FROM place
WHERE bbox IS NOT NULL
AND bbox.xmax >= {LON_MIN} AND bbox.xmin <= {LON_MAX}
AND bbox.ymax >= {LAT_MIN} AND bbox.ymin <= {LAT_MAX}
),
h3 AS (
SELECT h3_longlatash3(lon, lat, {H3_RES}) AS h3
FROM base
)
SELECT
h3_boundaryaswkt(h3) AS wkt,
COUNT(*) AS cnt
FROM h3
GROUP BY 1
ORDER BY cnt DESC
LIMIT {LIMIT_N}
"""
# ============================================================
# Databricks 実行
# ============================================================
t0 = time.perf_counter()
with sql.connect(server_hostname=HOSTNAME, http_path=HTTP_PATH, access_token=TOKEN) as conn, conn.cursor() as cur:
cur.execute(f"USE CATALOG `{CATALOG}`")
cur.execute(f"USE SCHEMA `{SCHEMA}`")
cur.execute(QUERY)
rows = cur.fetchall()
print(f"[TIME] Databricks SQL: {time.perf_counter() - t0:.2f}s")
# ============================================================
# QGIS レイヤ生成
# ============================================================
t0 = time.perf_counter()
layer = QgsVectorLayer("Polygon?crs=EPSG:4326", f"Tokyo23_Place_H3_r{H3_RES}", "memory")
prov = layer.dataProvider()
prov.addAttributes([QgsField("cnt", QVariant.Int)])
layer.updateFields()
feats = []
for wkt, cnt in rows:
if not wkt:
continue
g = QgsGeometry.fromWkt(wkt)
if g.isEmpty():
continue
f = QgsFeature(layer.fields())
f.setGeometry(g)
f["cnt"] = int(cnt)
feats.append(f)
prov.addFeatures(feats)
print(f"[TIME] Layer build: {time.perf_counter() - t0:.2f}s")
# ============================================================
# QGIS表示
# ============================================================
t0 = time.perf_counter()
classes = 7
tmp = QgsGraduatedSymbolRenderer()
tmp.setClassAttribute("cnt")
tmp.setMode(QgsGraduatedSymbolRenderer.Quantile)
tmp.updateClasses(layer, classes)
ranges = []
for i, r in enumerate(tmp.ranges()):
sym = QgsSymbol.defaultSymbol(layer.geometryType())
# 白 → 濃赤(不透明)
t = i / max(1, classes - 1)
color = QColor(
int(255 - 75 * t), # R
int(255 * (1 - t)), # G
int(255 * (1 - t)), # B
255 # αは固定
)
sym.setColor(color)
# 最大値レンジだけ強調
if i == classes - 1:
sym.setOpacity(1.0)
label = f"{int(r.lowerValue())} – {int(r.upperValue())}"
ranges.append(QgsRendererRange(r.lowerValue(), r.upperValue(), sym, label))
renderer = QgsGraduatedSymbolRenderer("cnt", ranges)
renderer.setMode(QgsGraduatedSymbolRenderer.Quantile)
layer.setRenderer(renderer)
# レイヤ全体を 70% 透明に
layer.setOpacity(0.8)
print(f"[TIME] Renderer: {time.perf_counter() - t0:.2f}s")
# ============================================================
# 表示
# ============================================================
QgsProject.instance().addMapLayer(layer)
iface.mapCanvas().setExtent(layer.extent())
iface.mapCanvas().refresh()
print(f"[TIME] TOTAL: {time.perf_counter() - T_ALL:.2f}s")
また、上記コードを日本の矩形でH3indexの解像度4だと18秒ほどで表示されます。
このほかにも、DataBricksのMarketplaceにあるcarto_overture_maps_transportationデータを用いて東京都23区矩形でのH3あたりの道路長なども10秒ほどで計算することが可能です。
おわりに
このように、DataBricksからQGISにも様々なデータが持ってこれる事がわかりました。
下図はとりあえず全世界のPlaceをチューニングした集計でやってみると5400万件30秒ほどで出してくれるのでなかなかですね、もっとDBに詳しいひとがいじるともっと早いかもしれません。
また、DataBricksのAIへもリクエストを投げることができそうなのですが、ちょっとややこしいのでそれはまたこんどの機会に












