空のベクトル検索エンドポイントの特定と削除
このページでは、空のベクトル検索エンドポイントを識別して削除する方法について説明します。ベクトル検索エンドポイントはワークスペース固有のリソースであるため、ワークスペースごとにこのプロセスを個別に繰り返す必要があります。
必要条件
- Databricks SDK for Python (
databricks-sdk
) です。 - Databricks ベクトル検索 Python SDK (
databricks-vectorsearch
)。 - 認証が構成されている(OAuth、PAT、または構成プロファイル)。
CAN_MANAGE
ターゲットワークスペースのベクトル検索エンドポイントの権限。
必要な SDK を Databricks ノートブックまたはローカル Python 環境にインストールするには:
# In a Databricks notebook
%pip install databricks-sdk databricks-vectorsearch
# In local Python environment
# pip install databricks-sdk databricks-vectorsearch
空のエンドポイントを特定する
Databricks UIでは、ベクトル検索エンドポイントは コンピュート 画面の ベクトル検索 タブに表示されます。[ エンドポイントを空にする] チェックボックスを切り替えて、インデックスが関連付けられていないエンドポイントを表示します。空の端点には、図のように警告三角形のアイコンも表示されます。
認証
ここでは、認証オプションについて説明します。
オプション 1.Databricks ノートブック内で実行する
Databricks ワークスペース ノートブックでコードを実行すると、認証は自動的に行われます。
from databricks.vector_search.client import VectorSearchClient
# Credentials are picked up automatically from notebook context
client = VectorSearchClient()
オプション 2.個人用アクセス トークン (PAT)
外部環境の場合は、明示的な資格情報を指定します。
from databricks.vector_search.client import VectorSearchClient
client = VectorSearchClient(
workspace_url="https://<your-instance>.cloud.databricks.com",
personal_access_token="dapiXXXXXXXXXXXXXXXXXXXXXXXX"
)
オプション 3.構成プロファイルを使用する (複数のワークスペースに推奨)
ホームディレクトリに .databrickscfg
ファイルを作成し、各ワークスペースのプロファイルを含めます。
[DEFAULT]
host = https://workspace1.cloud.databricks.com
token = dapiXXXXXXXXXXXXXXXXXXXXXXXX
[PRODUCTION]
host = https://workspace2.cloud.databricks.com
token = dapiYYYYYYYYYYYYYYYYYYYYYYYY
[DEVELOPMENT]
host = https://workspace3.cloud.databricks.com
token = dapiZZZZZZZZZZZZZZZZZZZZZZZZ
構成プロファイルを使用したくない場合は、資格情報を直接指定できます。
# Define workspaces with explicit credentials
workspace_configs = [
{
'workspace_url': 'https://workspace1.cloud.databricks.com',
'token': 'dapiXXXXXXXXXXXXXXXXXXXXXXXX'
},
{
'workspace_url': 'https://workspace2.cloud.databricks.com',
'token': 'dapiYYYYYYYYYYYYYYYYYYYYYYYY'
}
]
# Run cleanup, set `dry_run=False` to perform actual deletion
results = cleanup_multiple_workspaces(workspace_configs, dry_run=True)
1 つのワークスペース内のエンドポイントを削除する
ベクトル検索エンドポイントはワークスペース固有です。 これは、1 つのワークスペース内の空のエンドポイントを検索して削除するための基本的なスクリプトです。複数のワークスペースにまたがる空のエンドポイントをクリーンアップするには、「 複数のワークスペースにまたがるエンドポイントの削除」を参照してください。
エンドポイントの削除は元に戻せません。オプション dry_run=True
を使用して、削除されるエンドポイントのリストを表示します。リストが正しいことを確認したら、 dry_run=False
を使用してスクリプトを実行します。
from databricks.vector_search.client import VectorSearchClient
def cleanup_empty_endpoints(client, dry_run=True):
"""
Find and delete empty Vector Search endpoints.
Args:
client: VectorSearchClient instance
dry_run: If True, only print what would be deleted without actually deleting
Returns:
List of deleted endpoint names
"""
deleted_endpoints = []
# List all Vector Search endpoints
endpoints = client.list_endpoints()
for endpoint in endpoints["endpoints"]:
# List indexes in this endpoint
indexes = list(client.list_indexes(name=endpoint["name"])['vector_indexes'])
if len(indexes) == 0:
if dry_run:
print(f"[DRY RUN] Would delete empty endpoint: '{endpoint["name"]}'")
else:
print(f"Deleting empty endpoint: '{endpoint["name"]}'")
try:
client.delete_endpoint(endpoint["name"])
deleted_endpoints.append(endpoint["name"])
print(f"✓ Successfully deleted: {endpoint["name"]}")
except Exception as e:
print(f"✗ Failed to delete {endpoint["name"]}: {str(e)}")
else:
print(f"Endpoint '{endpoint["name"]}' has {len(indexes)} indexes - keeping")
return deleted_endpoints
# Example usage
client = VectorSearchClient() # Uses default authentication
# Set `dry_run=False` when you are ready to delete endpoints
deleted = cleanup_empty_endpoints(client, dry_run=True)
print(f"\nTotal endpoints deleted: {len(deleted)}")
複数のワークスペースにまたがるエンドポイントを削除する
複数のワークスペースにまたがる空のエンドポイントをクリーンアップするには、構成プロファイルを反復処理します。
-
エンドポイントの削除は元に戻せません。オプション
dry_run=True
を使用して、削除されるエンドポイントのリストを表示します。リストが正しいことを確認したら、dry_run=False
を使用してスクリプトを実行します。 -
多くのワークスペースを処理する場合は、API レート制限に注意してください。必要に応じて遅延を追加します。
Pythonimport time
for config in workspace_configs:
# Set `dry_run=False` to perform actual deletion
result = cleanup_workspace(**config, dry_run=True)
time.sleep(2) # Add delay between workspaces
from databricks.sdk import WorkspaceClient
from databricks.vector_search.client import VectorSearchClient
import logging
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
def cleanup_workspace(profile_name=None, workspace_url=None, token=None, dry_run=True):
"""
Clean up empty endpoints in a specific workspace.
Args:
profile_name: Name of configuration profile to use
workspace_url: Direct workspace URL (if not using profile)
token: PAT token (if not using profile)
dry_run: If True, only show what would be deleted
Returns:
Dict with cleanup results
"""
try:
# Initialize client based on authentication method
if profile_name:
# Use Databricks SDK to get credentials from profile
w = WorkspaceClient(profile=profile_name)
workspace_url = w.config.host
client = VectorSearchClient(
workspace_url=workspace_url,
personal_access_token=w.config.token
)
logger.info(f"Connected to workspace using profile '{profile_name}': {workspace_url}")
elif workspace_url and token:
client = VectorSearchClient(
workspace_url=workspace_url,
personal_access_token=token
)
logger.info(f"Connected to workspace: {workspace_url}")
else:
# Use default authentication (notebook context)
client = VectorSearchClient()
logger.info("Connected using default authentication")
# Perform cleanup
deleted = cleanup_empty_endpoints(client, dry_run=dry_run)
return {
'workspace': workspace_url or 'default',
'success': True,
'deleted_count': len(deleted),
'deleted_endpoints': deleted
}
except Exception as e:
logger.error(f"Failed to process workspace: {str(e)}")
return {
'workspace': workspace_url or profile_name or 'default',
'success': False,
'error': str(e)
}
def cleanup_multiple_workspaces(workspace_configs, dry_run=True):
"""
Clean up empty endpoints across multiple workspaces.
Args:
workspace_configs: List of workspace configurations
dry_run: If True, only show what would be deleted
Returns:
Summary of cleanup results
"""
results = []
for config in workspace_configs:
logger.info(f"\n{'='*60}")
result = cleanup_workspace(**config, dry_run=dry_run)
results.append(result)
logger.info(f"{'='*60}\n")
# Print summary
total_deleted = sum(r['deleted_count'] for r in results if r['success'])
successful = sum(1 for r in results if r['success'])
failed = sum(1 for r in results if not r['success'])
logger.info("\n" + "="*60)
logger.info("CLEANUP SUMMARY")
logger.info("="*60)
logger.info(f"Workspaces processed: {len(results)}")
logger.info(f"Successful: {successful}")
logger.info(f"Failed: {failed}")
logger.info(f"Total endpoints deleted: {total_deleted}")
if failed > 0:
logger.warning("\nFailed workspaces:")
for r in results:
if not r['success']:
logger.warning(f" - {r['workspace']}: {r['error']}")
return results
# Example: Clean up using configuration profiles
workspace_configs = [
{'profile_name': 'DEFAULT'},
{'profile_name': 'PRODUCTION'},
{'profile_name': 'DEVELOPMENT'}
]
# Set `dry_run=False` to do actual deletion.
results = cleanup_multiple_workspaces(workspace_configs, dry_run=True)
カスタムフィルタリング
カスタムロジックを追加して、次のように特定のエンドポイントを削除から除外できます。
def should_delete_endpoint(endpoint, indexes):
"""
Custom logic to determine if an endpoint should be deleted.
Args:
endpoint: Endpoint object
indexes: List of indexes in the endpoint
Returns:
Boolean indicating if endpoint should be deleted
"""
# Don't delete if it has indexes
if len(indexes) > 0:
return False
# Don't delete endpoints with specific naming patterns
protected_patterns = ['prod-', 'critical-', 'do-not-delete']
for pattern in protected_patterns:
if pattern in endpoint.name.lower():
logger.warning(f"Skipping protected endpoint: {endpoint.name}")
return False
# Add more custom logic as needed
return True
結果のエクスポート
クリーンアップ結果を監査用にファイルに保存するには:
import json
from datetime import datetime
def export_results(results, filename=None):
"""Export cleanup results to JSON file."""
if not filename:
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
filename = f'vector_search_cleanup_{timestamp}.json'
with open(filename, 'w') as f:
json.dump({
'timestamp': datetime.now().isoformat(),
'results': results
}, f, indent=2)
logger.info(f"Results exported to: {filename}")
トラブルシューティング
認証の問題
- PAT トークンが有効で、有効期限が切れていないことを確認します。
- 構成プロファイルが正しくフォーマットされていることを確認します。
- トークンに必要な権限があることを確認します。
権限エラー
ユーザーまたはサービスプリンシパルにベクトル検索エンドポイントに対する CAN_MANAGE
権限があることを確認します。
ネットワークの問題
プロキシ要件のある環境では、SDK を適切に構成します。
import os
os.environ['HTTPS_PROXY'] = 'http://your-proxy:po
次のステップ
- このスクリプトをスケジュールして、 LakeFlowジョブを使用して定期的に実行します。
- Infrastructure-as-Codeパイプラインと統合します。
- クリーンアップの概要に Eメール または Slack 通知を追加します。
- ダッシュボードを作成して、ワークスペース間でエンドポイントの使用状況を追跡します。