はじめに
ここまでの記事で、Databricks Appsでアプリケーションを作成したり、SQLウェアハウスを構築したりしてきました。
この記事では、これらを組み合わせて、Databricks Appsで作成したアプリケーションからDatabricks SQLウェアハウスに接続する方法を解説します。
前段
- Azure DatabricksでDatabricks Appsを検証するための環境構築
- Databricks Apps でカスタムアプリのデプロイ
- FastAPIにSPAアプリケーションを統合する
- Databricks AppsにSPAアプリを含めたカスタムアプリを作成する
- Databricks WorkspaceとGitHubを連携してDatabricks Appsにデプロイする
- Databricks WebTerminalを有効化する
- DatabricksでSQLウェアハウスを構築して、SQLAlchemy+AlembicでDB Migrationを行う
手順
※ コードベースは過去の記事のものを使用しています
-
必要なライブラリの追加
# SQLAlchemyをインストールします。これはPythonのSQLツールキットで、データベースとの対話を容易にします。 pip install sqlalchemy # Alembicをインストールします。これはSQLAlchemyのためのデータベースマイグレーションツールです。 pip install alembic # Databricks専用のSQLAlchemyアダプタをインストールします。 pip install databricks-sqlalchemy # Databricks SQL Connectorをインストールします。これはDatabricksとの効率的なデータベース接続を提供します。 pip install databricks-sql-connector
-
BackendにCRUD用APIを作成
例)@app.get("/api/items/", response_model=List[ItemResponse]) def read_items( q: Optional[str] = None, skip: int = 0, limit: int = 100, db: Session = Depends(get_db) ): logger.info(f"Fetching items with query: {q}, skip: {skip}, limit: {limit}") query = db.query(Item) if q: query = query.filter( or_( Item.item_id.ilike(f"%{q}%"), Item.query.ilike(f"%{q}%") ) ) items = query.offset(skip).limit(limit).all() return items
-
BackendのDB接続用処理を作成
AlembicのMigrationではカタログとスキーマを指定していましたが、アプリで設定すると接続がうまくいかなかったため、
他の3項目を指定して接続します。
DATABASE_URL = f"databricks://token:{DATABRICKS_TOKEN}@{DATABRICKS_SERVER_HOSTNAME}?http_path={DATABRICKS_HTTP_PATH}"
engine = create_engine(DATABASE_URL, connect_args={"verify": False}, echo=True)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
-
app.yamlにDB接続用の環境変数を設定
環境変数に登録するには、app.yamlのenvに以下のように設定します。command: [ "gunicorn", "main:app", "-k", "uvicorn.workers.UvicornWorker", "-w", "4", ], env: - DATABRICKS_SERVER_HOSTNAME_PROD <Databricksのホスト名> - DATABRICKS_HTTP_PATH_PROD <DatabricksのHTTPパス> - DATABRICKS_TOKEN_PROD <Databricksのアクセストークン>
-
Frontendのビルド&Backendのstaticフォルダへビルドしたファイルを配置
# フロントエンドディレクトリに移動 cd frontend # 静的ファイルを生成 npm run generate # 古い静的ファイルをバックエンドディレクトリから削除 rm -rf ../backend/static # 新しく生成した静的ファイルをバックエンドのstaticディレクトリにコピー cp -r .output/public ../backend/static
-
Gitコミット&Githubへのデプロイ後、Databricks Appsへデプロイ
参考:Databricks WorkspaceとGitHubを連携してDatabricks Appsにデプロイするgit add . git commit -m "Databricks Appsへデプロイ" git push cd ./backend databricks apps deploy --app-name <app_name> --source-code-path /Workspace/Users/<username>/<repo_name>/...
つまづきポイント
- DatabricksのUnity CatalogでCreateIndexを実行すると、
The command(s): CreateIndex are not supported in Unity Catalog.
が発生- マイグレーションファイルでCreateIndexを実行していた
- Unity Catalogをやめてしまうとマイグレーションの実行に失敗する
- マイグレーションファイルでIndex作成部分を手動削除することで解決
- アプリ起動時に
sqlalchemy.exc.NoSuchModuleError: Cant load plugin: sqlalchemy.dialects:databricks
が発生- databricks-sqlalchemyかdatabricks-sql-connectorのあたりがないことが原因
- Insert文の実行時に、
[DELTA_INSERT_COLUMN_MISMATCH] Column id is not specified in INSERT
が発生- テーブルのidをオートインクリメントの設定にしていた
- オートインクリメントの設定を削除し、インサートの度にidを指定することで解決
- UUIDに変更
- UUIDに変更した後、
INVALID_NON_DETERMINISTIC_EXPRESSIONS] The operator expects a deterministic expression, but the actual expression is "columndefinition
が発生- IDが非決定性式であることが原因
- UUIDを文字列として扱うように修正
補足
- Databricks AppsへのアクセスはDatabricksへの認証済みでないとアクセスできないのか検証
- シークレットウィンドウで開くと、認証画面が表示される
- apiを実行するとエラーではなく、空レスポンスが返ってくる
- ということで、Databricks Appsはアプリ側で認証を実装しなくてもDatabricksの認証機構を使ってアクセス制御ができることがわかった
まとめ
この記事では、Databricks AppsからDatabricks SQLウェアハウスへの接続方法について説明しました。
主なポイントは以下の通りです:
- SQLAlchemy、Alembic、Databricks専用のSQLAlchemyアダプタなど、必要なライブラリの導入
- バックエンドでのCRUD APIの実装とDB接続処理の設定
- app.yamlでの環境変数設定による接続情報の管理
- フロントエンドからバックエンドAPIを呼び出す実装
また、実装時の主な課題とその解決方法も記載しました:
- Unity CatalogでのCreateIndex実行時の制限
- SQLAlchemy関連の依存関係の問題
- IDカラムの扱いに関する問題(オートインクリメント、UUID)