codebuff-agent 2.1.74__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- codebuff_agent-2.1.74.data/data/etc/jupyter/jupyter_server_config.d/codebuff_agent.json +7 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/package.json +157 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/104.2b8f20f9d1ac2c9db01b.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/150.39fa98117cc8ca590465.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/166.386ff9b2c37ac865fdee.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/216.25cf81131bf7274dabf4.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/353.581bd1cb00746399b62e.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/367.575f9621b63c9a641aa9.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/421.11dac223a2c2da1b09f5.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/432.8513b4c6cc1d1232d165.js +2 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/432.8513b4c6cc1d1232d165.js.LICENSE.txt +19 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/439.ba5b5ef70ec6de214b8c.js +2 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/439.ba5b5ef70ec6de214b8c.js.LICENSE.txt +8 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/481.cc2dec9fa869d66f1407.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/487.0796e931d6e651482c14.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/49.d326f554b6f9ccde6580.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/541.26897ea32845659e36be.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/579.e569d3edd8391fd8fbb3.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/58.eb7cc679f7535cc8a2f1.js +2 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/58.eb7cc679f7535cc8a2f1.js.LICENSE.txt +8 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/666.d9bfdb23f98489d0a188.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/677.d266c39dbed33bc388b3.js +2 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/677.d266c39dbed33bc388b3.js.LICENSE.txt +8 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/68.26b6f59c8454adb17f20.js +204 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/694.4ac443814260057e68f7.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/791.61affb8d3480d3d60e0d.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/848.4d2db09cfbb09374b299.js +2 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/848.4d2db09cfbb09374b299.js.LICENSE.txt +9 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/868.5cfe7e1a348ec5af1b8c.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/97.ea559a5b8a9a09f17c6b.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/remoteEntry.5292fc9c6df7e7920cc8.js +1 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/style.js +4 -0
- codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/third-party-licenses.json +724 -0
- codebuff_agent-2.1.74.dist-info/METADATA +142 -0
- codebuff_agent-2.1.74.dist-info/RECORD +217 -0
- codebuff_agent-2.1.74.dist-info/WHEEL +4 -0
- codebuff_agent-2.1.74.dist-info/licenses/LICENSE +21 -0
- codebuff_core/__init__.py +153 -0
- codebuff_core/codebuff_config_defaults.json +64 -0
- codebuff_core/core/__init__.py +35 -0
- codebuff_core/core/code_validator.py +1238 -0
- codebuff_core/core/error_classifier.py +579 -0
- codebuff_core/core/exceptions.py +49 -0
- codebuff_core/data/tiktoken_cache/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +100256 -0
- codebuff_core/directory_policy.py +32 -0
- codebuff_core/factory.py +155 -0
- codebuff_core/interfaces.py +197 -0
- codebuff_core/knowledge/__init__.py +31 -0
- codebuff_core/knowledge/chunking.py +375 -0
- codebuff_core/knowledge/loader.py +339 -0
- codebuff_core/knowledge/watchdog_service.py +354 -0
- codebuff_core/legacy_paths.py +69 -0
- codebuff_core/llm/__init__.py +13 -0
- codebuff_core/llm/service.py +407 -0
- codebuff_core/managers/__init__.py +22 -0
- codebuff_core/managers/config_manager.py +690 -0
- codebuff_core/managers/remote_config.py +673 -0
- codebuff_core/managers/remote_skills.py +539 -0
- codebuff_core/managers/session_manager.py +255 -0
- codebuff_core/middleware/__init__.py +3 -0
- codebuff_core/middleware/error_recovery.py +394 -0
- codebuff_core/middleware/logging_utils.py +33 -0
- codebuff_core/models/__init__.py +111 -0
- codebuff_core/models/agent.py +306 -0
- codebuff_core/models/chat.py +57 -0
- codebuff_core/models/common.py +82 -0
- codebuff_core/models/rag.py +300 -0
- codebuff_core/platform_rules.py +127 -0
- codebuff_core/prompts/__init__.py +44 -0
- codebuff_core/prompts/auto_agent_prompts.py +1278 -0
- codebuff_core/services/__init__.py +30 -0
- codebuff_core/services/agent_service.py +345 -0
- codebuff_core/services/analytics_aggregate.py +837 -0
- codebuff_core/services/chat_service.py +898 -0
- codebuff_core/services/context_condenser.py +306 -0
- codebuff_core/services/pii_guardrail.py +393 -0
- codebuff_core/services/rag_chat_agent.py +2993 -0
- codebuff_core/services/rag_collections.py +2740 -0
- codebuff_core/services/rag_manager.py +890 -0
- codebuff_core/services/rag_service.py +145 -0
- codebuff_core/services/retriever.py +260 -0
- codebuff_core/services/vllm_embedding_service.py +290 -0
- codebuff_core/tests/__init__.py +1 -0
- codebuff_core/tests/conftest.py +81 -0
- codebuff_core/tests/test_error_recovery.py +647 -0
- codebuff_core/tests/test_factory.py +135 -0
- codebuff_core/tests/test_services.py +150 -0
- jupyter_ext/__init__.py +266 -0
- jupyter_ext/_version.py +4 -0
- jupyter_ext/agent/__init__.py +49 -0
- jupyter_ext/agent/agent_factory.py +2270 -0
- jupyter_ext/agent/ast_tools.py +451 -0
- jupyter_ext/agent/autofix_middleware.py +481 -0
- jupyter_ext/agent/background_procs.py +372 -0
- jupyter_ext/agent/code_history_middleware.py +211 -0
- jupyter_ext/agent/codex_autofix.py +160 -0
- jupyter_ext/agent/codex_bridge.py +3339 -0
- jupyter_ext/agent/codex_hooks.py +320 -0
- jupyter_ext/agent/codex_slash.py +685 -0
- jupyter_ext/agent/codex_threads.py +114 -0
- jupyter_ext/agent/content_injection.py +377 -0
- jupyter_ext/agent/continuation_middleware.py +548 -0
- jupyter_ext/agent/custom_skills.py +335 -0
- jupyter_ext/agent/file_diffs.py +99 -0
- jupyter_ext/agent/git_history.py +188 -0
- jupyter_ext/agent/guardrail_middleware.py +421 -0
- jupyter_ext/agent/json_repair_utils.py +54 -0
- jupyter_ext/agent/langchain_tools.py +2673 -0
- jupyter_ext/agent/mermaid_fixer.py +289 -0
- jupyter_ext/agent/mermaid_middleware.py +135 -0
- jupyter_ext/agent/middleware.py +359 -0
- jupyter_ext/agent/middleware_prompts.py +53 -0
- jupyter_ext/agent/observability.py +334 -0
- jupyter_ext/agent/patch_tool_calls.py +57 -0
- jupyter_ext/agent/prompts.py +112 -0
- jupyter_ext/agent/skill_middleware.py +257 -0
- jupyter_ext/agent/skills/airflow_dag_development.md +36 -0
- jupyter_ext/agent/skills/anomaly_detection.md +12 -0
- jupyter_ext/agent/skills/athena_sql.md +156 -0
- jupyter_ext/agent/skills/bdp_table_search.md +33 -0
- jupyter_ext/agent/skills/bigquery.md +65 -0
- jupyter_ext/agent/skills/bigquery_oracle.md +231 -0
- jupyter_ext/agent/skills/bigquery_tuning.md +307 -0
- jupyter_ext/agent/skills/classification_evaluation.md +11 -0
- jupyter_ext/agent/skills/clustering_analysis.md +12 -0
- jupyter_ext/agent/skills/comprehensive_eda.md +11 -0
- jupyter_ext/agent/skills/data_analysis.md +236 -0
- jupyter_ext/agent/skills/data_cleaning_pipeline.md +12 -0
- jupyter_ext/agent/skills/data_loading.md +158 -0
- jupyter_ext/agent/skills/data_quality_report.md +13 -0
- jupyter_ext/agent/skills/dimensionality_reduction.md +12 -0
- jupyter_ext/agent/skills/emr_script_development.md +17 -0
- jupyter_ext/agent/skills/experiment_tracking.md +13 -0
- jupyter_ext/agent/skills/feature_importance_analysis.md +10 -0
- jupyter_ext/agent/skills/hyperparameter_tuning.md +12 -0
- jupyter_ext/agent/skills/hypothesis_testing.md +12 -0
- jupyter_ext/agent/skills/imbalanced_data_handling.md +12 -0
- jupyter_ext/agent/skills/inference.md +392 -0
- jupyter_ext/agent/skills/lambda_function_development.md +19 -0
- jupyter_ext/agent/skills/model_comparison.md +11 -0
- jupyter_ext/agent/skills/model_explainability.md +12 -0
- jupyter_ext/agent/skills/model_training.md +318 -0
- jupyter_ext/agent/skills/pyspark.md +352 -0
- jupyter_ext/agent/skills/python_code_quality.md +35 -0
- jupyter_ext/agent/skills/regression_evaluation.md +12 -0
- jupyter_ext/agent/skills/spring_java_development.md +35 -0
- jupyter_ext/agent/skills/text_preprocessing.md +12 -0
- jupyter_ext/agent/skills/time_series_analysis.md +13 -0
- jupyter_ext/agent/skills/unit_testing.md +203 -0
- jupyter_ext/agent/todo_prompts.py +57 -0
- jupyter_ext/agent/tool_report.py +45 -0
- jupyter_ext/analytics_ingest.py +599 -0
- jupyter_ext/etc/jupyter/jupyter_server_config.d/codebuff_agent.json +7 -0
- jupyter_ext/handlers/__init__.py +8 -0
- jupyter_ext/handlers/analytics_handler.py +170 -0
- jupyter_ext/handlers/benchmark_handler.py +794 -0
- jupyter_ext/handlers/eda_benchmark_handler.py +1328 -0
- jupyter_ext/handlers/rag_admin_handler.py +689 -0
- jupyter_ext/handlers/websocket.py +497 -0
- jupyter_ext/http_handlers.py +8744 -0
- jupyter_ext/idle_monitor.py +346 -0
- jupyter_ext/labextension/package.json +157 -0
- jupyter_ext/labextension/static/104.2b8f20f9d1ac2c9db01b.js +1 -0
- jupyter_ext/labextension/static/150.39fa98117cc8ca590465.js +1 -0
- jupyter_ext/labextension/static/166.386ff9b2c37ac865fdee.js +1 -0
- jupyter_ext/labextension/static/216.25cf81131bf7274dabf4.js +1 -0
- jupyter_ext/labextension/static/353.581bd1cb00746399b62e.js +1 -0
- jupyter_ext/labextension/static/367.575f9621b63c9a641aa9.js +1 -0
- jupyter_ext/labextension/static/421.11dac223a2c2da1b09f5.js +1 -0
- jupyter_ext/labextension/static/432.8513b4c6cc1d1232d165.js +2 -0
- jupyter_ext/labextension/static/432.8513b4c6cc1d1232d165.js.LICENSE.txt +19 -0
- jupyter_ext/labextension/static/439.ba5b5ef70ec6de214b8c.js +2 -0
- jupyter_ext/labextension/static/439.ba5b5ef70ec6de214b8c.js.LICENSE.txt +8 -0
- jupyter_ext/labextension/static/481.cc2dec9fa869d66f1407.js +1 -0
- jupyter_ext/labextension/static/487.0796e931d6e651482c14.js +1 -0
- jupyter_ext/labextension/static/49.d326f554b6f9ccde6580.js +1 -0
- jupyter_ext/labextension/static/541.26897ea32845659e36be.js +1 -0
- jupyter_ext/labextension/static/579.e569d3edd8391fd8fbb3.js +1 -0
- jupyter_ext/labextension/static/58.eb7cc679f7535cc8a2f1.js +2 -0
- jupyter_ext/labextension/static/58.eb7cc679f7535cc8a2f1.js.LICENSE.txt +8 -0
- jupyter_ext/labextension/static/666.d9bfdb23f98489d0a188.js +1 -0
- jupyter_ext/labextension/static/677.d266c39dbed33bc388b3.js +2 -0
- jupyter_ext/labextension/static/677.d266c39dbed33bc388b3.js.LICENSE.txt +8 -0
- jupyter_ext/labextension/static/68.26b6f59c8454adb17f20.js +204 -0
- jupyter_ext/labextension/static/694.4ac443814260057e68f7.js +1 -0
- jupyter_ext/labextension/static/791.61affb8d3480d3d60e0d.js +1 -0
- jupyter_ext/labextension/static/848.4d2db09cfbb09374b299.js +2 -0
- jupyter_ext/labextension/static/848.4d2db09cfbb09374b299.js.LICENSE.txt +9 -0
- jupyter_ext/labextension/static/868.5cfe7e1a348ec5af1b8c.js +1 -0
- jupyter_ext/labextension/static/97.ea559a5b8a9a09f17c6b.js +1 -0
- jupyter_ext/labextension/static/remoteEntry.5292fc9c6df7e7920cc8.js +1 -0
- jupyter_ext/labextension/static/style.js +4 -0
- jupyter_ext/labextension/static/third-party-licenses.json +724 -0
- jupyter_ext/log_paths.py +113 -0
- jupyter_ext/resource_usage.py +519 -0
- jupyter_ext/secrets_bootstrap.py +116 -0
- jupyter_ext/team_access.py +105 -0
- jupyter_ext/tests/__init__.py +1 -0
- jupyter_ext/tests/test_context.py +234 -0
- jupyter_ext/tests/test_factory.py +563 -0
- jupyter_ext/tests/test_file_finder.py +139 -0
- jupyter_ext/tests/test_handlers.py +58 -0
- jupyter_ext/tests/test_mcp_selftest.py +204 -0
- jupyter_ext/tests/test_mermaid_fixer.py +272 -0
- jupyter_ext/tests/test_resource_tiers.py +298 -0
- jupyter_ext/tools/__init__.py +15 -0
- jupyter_ext/tools/base.py +90 -0
- jupyter_ext/tools/context.py +268 -0
- jupyter_ext/tools/dir_complete.py +86 -0
- jupyter_ext/tools/file_finder.py +303 -0
- jupyter_ext/tools/file_tools.py +244 -0
- jupyter_ext/tools/jupyter_tools.py +296 -0
- jupyter_ext/tools/registry.py +159 -0
- jupyter_ext/tools/search_tools.py +230 -0
- jupyter_ext/tools/security_tools.py +657 -0
- jupyter_ext/tools/shell_tools.py +109 -0
- jupyter_ext/tools/user_tools.py +132 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bigquery_oracle
|
|
3
|
+
description: Oracle(Exadata) → BigQuery SQL 변환. 구문 매핑, 실행 모델 비교, Hint 대체 전략.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Oracle(Exadata) → BigQuery 변환 가이드
|
|
7
|
+
|
|
8
|
+
### 구문 매핑 테이블
|
|
9
|
+
|
|
10
|
+
| Oracle 구문 | BigQuery StandardSQL 대체 |
|
|
11
|
+
|-------------|--------------------------|
|
|
12
|
+
| `ROWNUM` | `ROW_NUMBER() OVER()` |
|
|
13
|
+
| `NVL(a, b)` | `IFNULL(a, b)` / `COALESCE(a, b)` |
|
|
14
|
+
| `NVL2(a, b, c)` | `IF(a IS NOT NULL, b, c)` |
|
|
15
|
+
| `DECODE(a, v1, r1, ...)` | `CASE WHEN a = v1 THEN r1 ... END` |
|
|
16
|
+
| `SYSDATE` | `CURRENT_TIMESTAMP()` |
|
|
17
|
+
| `TO_DATE(s, fmt)` | `PARSE_DATE(fmt, s)` (포맷 문법 다름) |
|
|
18
|
+
| `TO_CHAR(d, fmt)` | `FORMAT_DATE(fmt, d)` / `FORMAT_TIMESTAMP()` |
|
|
19
|
+
| `(+)` outer join | `LEFT JOIN` / `RIGHT JOIN` |
|
|
20
|
+
| `CONNECT BY / START WITH` | Recursive CTE (`WITH RECURSIVE`) |
|
|
21
|
+
| `MINUS` | `EXCEPT DISTINCT` |
|
|
22
|
+
| `FROM DUAL` | FROM 생략 가능 (BQ) |
|
|
23
|
+
| `MERGE INTO` | `MERGE` (BQ DML, 구문 유사) |
|
|
24
|
+
| `ROWID` | 없음 (partition/clustering으로 대체) |
|
|
25
|
+
| `SEQUENCE` | `GENERATE_UUID()` / `ROW_NUMBER()` |
|
|
26
|
+
| `DBMS_*` 패키지 | BQ scripting / UDF |
|
|
27
|
+
| PL/SQL 프로시저 | BQ scripting (`DECLARE`, `SET`, `LOOP`, `IF`) |
|
|
28
|
+
| Oracle hint (`/*+ PARALLEL */`) | 불필요 (BQ 자동 병렬화) |
|
|
29
|
+
| `VARCHAR2(N)` | `STRING` |
|
|
30
|
+
| `NUMBER(p,s)` | `NUMERIC` / `INT64` / `FLOAT64` |
|
|
31
|
+
| `DATE` (Oracle은 timestamp 포함) | `TIMESTAMP` |
|
|
32
|
+
| `CLOB` / `BLOB` | `STRING` / `BYTES` |
|
|
33
|
+
|
|
34
|
+
### 성능 주의사항
|
|
35
|
+
- **Exadata 물리 인덱스 의존 쿼리** → BQ partition/clustering 전략으로 재설계 필요
|
|
36
|
+
- **Nested Loop Join 패턴** (Oracle index scan 기반) → BQ에서는 Hash Join으로 자동 전환, 대형 테이블 시 pre-filter 필수
|
|
37
|
+
- **PL/SQL 커서 반복** → BQ SET 기반 처리 (벡터 연산)로 재작성
|
|
38
|
+
- **Oracle Materialized View** → BQ Materialized View (구문/제약 다름, GROUP BY + 집계 함수만)
|
|
39
|
+
|
|
40
|
+
### Oracle vs BigQuery 실행 모델 비교
|
|
41
|
+
|
|
42
|
+
| 항목 | Oracle (Exadata) | BigQuery |
|
|
43
|
+
|------|-----------------|----------|
|
|
44
|
+
| **스토리지 구조** | Row-store + Smart Scan (column projection) | 완전 Columnar (Capacitor 포맷) |
|
|
45
|
+
| **인덱스** | B-tree, Bitmap, Function-based 등 | 없음 — Partition Pruning + Clustering으로 대체 |
|
|
46
|
+
| **JOIN 전략** | Nested Loop (index), Hash Join, Sort-Merge | Hash Join (shuffle/broadcast) — optimizer 자동 선택 |
|
|
47
|
+
| **정렬** | Index-ordered scan으로 sort 회피 가능 | 항상 명시적 sort (shuffle 필요), LIMIT 없으면 전체 데이터 정렬 |
|
|
48
|
+
| **병렬화** | `/*+ PARALLEL(N) */` hint로 수동 제어 | 자동 (슬롯 기반 분산), hint 불필요 |
|
|
49
|
+
| **캐싱** | Buffer Cache (SGA), Result Cache | 24시간 결과 캐시 (동일 쿼리 + 테이블 미변경 시) |
|
|
50
|
+
| **파티셔닝** | Range, List, Hash, Composite | 시간/정수 Range, Ingestion-time 파티션 |
|
|
51
|
+
| **통계 수집** | `DBMS_STATS`, `/*+ GATHER_PLAN_STATISTICS */` | 자동 (INFORMATION_SCHEMA.JOBS에 job_stages 포함) |
|
|
52
|
+
| **실행 계획** | `EXPLAIN PLAN`, SQL Monitor (`/*+ MONITOR */`) | 쿼리 실행 후 `INFORMATION_SCHEMA.JOBS.job_stages` 또는 Web UI |
|
|
53
|
+
|
|
54
|
+
### Oracle Hint → BQ 대체 전략
|
|
55
|
+
|
|
56
|
+
| Oracle Hint | Oracle 목적 | BQ 대체 전략 |
|
|
57
|
+
|-------------|-----------|-------------|
|
|
58
|
+
| `/*+ PARALLEL(N) */` | 병렬 실행 DOP 지정 | 불필요 — BQ 자동 슬롯 분배 |
|
|
59
|
+
| `/*+ FULL(t) */` | Full Table Scan 강제 | 불필요 — BQ 기본이 Full Scan (파티션 프루닝으로 범위 제한) |
|
|
60
|
+
| `/*+ INDEX(t idx) */` | 특정 인덱스 사용 강제 | 파티션 필터 + 클러스터링으로 scan 범위 축소 |
|
|
61
|
+
| `/*+ USE_HASH(t) */` | Hash Join 강제 | BQ 기본 전략, 작은 테이블은 broadcast join 자동 적용 |
|
|
62
|
+
| `/*+ USE_NL(t) */` | Nested Loop Join 강제 | BQ 미지원 — Hash Join으로 자동 대체 |
|
|
63
|
+
| `/*+ LEADING(t1 t2) */` | JOIN 순서 지정 | 불필요 — BQ optimizer 자동 결정 |
|
|
64
|
+
| `/*+ MONITOR */` | SQL Monitor 실시간 추적 | `INFORMATION_SCHEMA.JOBS`가 모든 쿼리 자동 기록 |
|
|
65
|
+
| `/*+ GATHER_PLAN_STATISTICS */` | 실행 통계 수집 | `job_stages` 필드에 stage별 통계 자동 포함 |
|
|
66
|
+
| `/*+ RESULT_CACHE */` | 결과 캐시 활성화 | BQ 24시간 자동 캐시 (동일 쿼리 + 테이블 미변경) |
|
|
67
|
+
| `/*+ NO_RESULT_CACHE */` | 캐시 우회 | `SELECT` 뒤에 `@{cache=false}` 힌트 사용 |
|
|
68
|
+
| `/*+ APPEND */` | Direct-path insert | BQ `INSERT`/`LOAD` 기본 동작 (append) |
|
|
69
|
+
| `/*+ PUSH_PRED */` | 조건 predicate pushdown | BQ optimizer 자동 적용 |
|
|
70
|
+
|
|
71
|
+
### 변환 시 Anti-Pattern 체크
|
|
72
|
+
|
|
73
|
+
Oracle에서 문제없지만 BQ에서 anti-pattern이 되는 패턴:
|
|
74
|
+
|
|
75
|
+
| Oracle 패턴 | BQ에서의 문제 | 권고 |
|
|
76
|
+
|------------|-------------|------|
|
|
77
|
+
| `ORDER BY col DESC` (LIMIT 없음) | BQ에서 전체 데이터 shuffle sort → 대량 slot 소비 | 반드시 `LIMIT N` 추가, 없으면 anti-pattern 경고 |
|
|
78
|
+
| `SELECT *` | Oracle은 row-store라 영향 적음, BQ는 columnar → 불필요 컬럼도 전부 scan | 필요 컬럼만 명시 (bytes_processed 대폭 감소) |
|
|
79
|
+
| `VARCHAR2` 컬럼 JOIN key | Oracle은 인덱스로 고속 매칭, BQ는 STRING Hash → 느림 | 가능하면 INT64 surrogate key 사용, 불가 시 클러스터링 적용 |
|
|
80
|
+
|
|
81
|
+
### 변환 시 Mermaid 시각화 예시
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
graph LR
|
|
85
|
+
subgraph "Oracle 구문"
|
|
86
|
+
O1["ROWNUM <= 10"]
|
|
87
|
+
O2["NVL(col, 0)"]
|
|
88
|
+
O3["DECODE(status, 'A', 'Active')"]
|
|
89
|
+
O4["table_a a, table_b b<br/>WHERE a.id = b.id(+)"]
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
subgraph "변환 규칙"
|
|
93
|
+
R1["ROW_NUMBER() OVER()"]
|
|
94
|
+
R2["IFNULL / COALESCE"]
|
|
95
|
+
R3["CASE WHEN"]
|
|
96
|
+
R4["LEFT JOIN"]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
subgraph "BigQuery 구문"
|
|
100
|
+
B1["ROW_NUMBER() OVER() <= 10"]
|
|
101
|
+
B2["IFNULL(col, 0)"]
|
|
102
|
+
B3["CASE WHEN status='A'<br/>THEN 'Active' END"]
|
|
103
|
+
B4["table_a a LEFT JOIN<br/>table_b b ON a.id=b.id"]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
O1 --> R1 --> B1
|
|
107
|
+
O2 --> R2 --> B2
|
|
108
|
+
O3 --> R3 --> B3
|
|
109
|
+
O4 --> R4 --> B4
|
|
110
|
+
|
|
111
|
+
style O1 fill:#EA4335,color:#fff
|
|
112
|
+
style O2 fill:#EA4335,color:#fff
|
|
113
|
+
style O3 fill:#EA4335,color:#fff
|
|
114
|
+
style O4 fill:#EA4335,color:#fff
|
|
115
|
+
style B1 fill:#34A853,color:#fff
|
|
116
|
+
style B2 fill:#34A853,color:#fff
|
|
117
|
+
style B3 fill:#34A853,color:#fff
|
|
118
|
+
style B4 fill:#34A853,color:#fff
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## ⚠️ 필수 출력 규칙
|
|
124
|
+
|
|
125
|
+
**모든 Oracle→BQ 변환 응답에는 반드시 ```mermaid 다이어그램을 포함하세요.**
|
|
126
|
+
- Oracle 실행 흐름 다이어그램 (graph TD)
|
|
127
|
+
- BigQuery 실행 흐름 다이어그램 (graph TD)
|
|
128
|
+
- 두 흐름의 비교가 시각적으로 드러나야 합니다.
|
|
129
|
+
- 다이어그램 없는 응답은 불완전한 응답입니다.
|
|
130
|
+
|
|
131
|
+
## 변환 예시 (Oracle 계층형 쿼리)
|
|
132
|
+
|
|
133
|
+
### 변환 개요
|
|
134
|
+
Oracle `CONNECT BY / START WITH` 계층형 쿼리를 BigQuery `WITH RECURSIVE` CTE로 변환합니다.
|
|
135
|
+
주요 변경사항:
|
|
136
|
+
- `START WITH ... CONNECT BY PRIOR` → `WITH RECURSIVE` CTE (base case + recursive step)
|
|
137
|
+
- `LEVEL` 의사컬럼 → CTE 내부 `depth` 컬럼으로 수동 계산
|
|
138
|
+
- `LPAD(' ', 2*(LEVEL-1))` → `REPEAT(' ', depth)` 로 대체
|
|
139
|
+
- `ORDER SIBLINGS BY` → BQ에서 직접 대응 없음, `path` 컬럼으로 정렬 구현
|
|
140
|
+
|
|
141
|
+
```sql
|
|
142
|
+
-- Oracle CONNECT BY → BigQuery WITH RECURSIVE 변환
|
|
143
|
+
WITH RECURSIVE org_tree AS (
|
|
144
|
+
-- Base case: 루트 노드 (manager_id IS NULL)
|
|
145
|
+
SELECT
|
|
146
|
+
employee_id,
|
|
147
|
+
employee_name,
|
|
148
|
+
manager_id,
|
|
149
|
+
0 AS depth,
|
|
150
|
+
-- 형제 정렬용 path (ORDER SIBLINGS BY 대체)
|
|
151
|
+
CAST(employee_name AS STRING) AS sort_path
|
|
152
|
+
FROM `project.dataset.employees`
|
|
153
|
+
WHERE manager_id IS NULL
|
|
154
|
+
|
|
155
|
+
UNION ALL
|
|
156
|
+
|
|
157
|
+
-- Recursive step: 자식 노드
|
|
158
|
+
SELECT
|
|
159
|
+
e.employee_id,
|
|
160
|
+
e.employee_name,
|
|
161
|
+
e.manager_id,
|
|
162
|
+
t.depth + 1,
|
|
163
|
+
CONCAT(t.sort_path, '/', e.employee_name)
|
|
164
|
+
FROM `project.dataset.employees` e
|
|
165
|
+
JOIN org_tree t ON e.manager_id = t.employee_id
|
|
166
|
+
)
|
|
167
|
+
SELECT
|
|
168
|
+
depth + 1 AS level,
|
|
169
|
+
CONCAT(REPEAT(' ', depth), employee_name) AS tree_name,
|
|
170
|
+
employee_id,
|
|
171
|
+
manager_id
|
|
172
|
+
FROM org_tree
|
|
173
|
+
ORDER BY sort_path
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### 구문 매핑 상세
|
|
177
|
+
|
|
178
|
+
| Oracle 구문 | BigQuery 대체 | 동작 차이 및 주의사항 |
|
|
179
|
+
|-------------|--------------|---------------------|
|
|
180
|
+
| `START WITH condition` | CTE base case `WHERE` | 동일한 필터 역할. BQ는 CTE 첫 번째 SELECT에 배치 |
|
|
181
|
+
| `CONNECT BY PRIOR a = b` | `JOIN org_tree t ON ...` | Oracle은 엔진 내부 트리 순회, BQ는 반복 JOIN |
|
|
182
|
+
| `LEVEL` | 수동 `depth` 컬럼 | Oracle은 자동 생성, BQ는 base=0에서 +1 누적 |
|
|
183
|
+
| `ORDER SIBLINGS BY name` | `sort_path` + `ORDER BY` | Oracle은 같은 부모 내 정렬 보장, BQ는 경로 문자열로 구현 |
|
|
184
|
+
| `LPAD(' ', 2*(LEVEL-1))` | `REPEAT(' ', depth)` | `LPAD`은 BQ에도 있지만 `REPEAT`이 가독성 우수 |
|
|
185
|
+
|
|
186
|
+
#### `ORDER SIBLINGS BY` 구현 상세
|
|
187
|
+
Oracle의 `ORDER SIBLINGS BY`는 **동일 부모(parent) 내에서만** 정렬을 보장합니다.
|
|
188
|
+
BQ의 `WITH RECURSIVE`에는 이 기능이 없으므로, `sort_path` 컬럼에 루트부터의 경로를 `/`로 연결하여 전체 트리를 사전순 정렬합니다.
|
|
189
|
+
단, 이름에 `/`가 포함된 경우 구분자 충돌 가능 → 해시나 zero-width 구분자 사용을 고려하세요.
|
|
190
|
+
|
|
191
|
+
### 실행 흐름 비교
|
|
192
|
+
|
|
193
|
+
#### Oracle 실행 흐름
|
|
194
|
+
```mermaid
|
|
195
|
+
graph TD
|
|
196
|
+
A[START WITH 조건으로 루트 행 선택] --> B[CONNECT BY PRIOR로 자식 행 탐색]
|
|
197
|
+
B --> C{자식 행 존재?}
|
|
198
|
+
C -->|Yes| D[LEVEL 자동 증가 + 트리에 추가]
|
|
199
|
+
D --> B
|
|
200
|
+
C -->|No| E[ORDER SIBLINGS BY로 형제 정렬]
|
|
201
|
+
E --> F[결과 반환]
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
#### BigQuery 실행 흐름
|
|
205
|
+
```mermaid
|
|
206
|
+
graph TD
|
|
207
|
+
A[Base CTE: WHERE manager_id IS NULL] --> B[depth=0 결과 임시 저장]
|
|
208
|
+
B --> C[Recursive step: employees JOIN org_tree]
|
|
209
|
+
C --> D{새 행 생성됨?}
|
|
210
|
+
D -->|Yes| E[depth+1, sort_path 연결]
|
|
211
|
+
E --> F[셔플 → 임시 저장]
|
|
212
|
+
F --> C
|
|
213
|
+
D -->|No| G[전체 결과 UNION ALL]
|
|
214
|
+
G --> H[ORDER BY sort_path]
|
|
215
|
+
H --> I[결과 반환]
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
| 항목 | Oracle | BigQuery |
|
|
219
|
+
|------|--------|----------|
|
|
220
|
+
| 실행 방식 | 내부 트리 순회 엔진 (O(n)) | 반복 JOIN (각 depth마다 전체 스캔) |
|
|
221
|
+
| 깊이 제한 | `CONNECT BY` 기본 1000 | `max_recursion_depth` 기본 500 |
|
|
222
|
+
| 메모리 | 작업 메모리에서 트리 구축 | 각 반복 결과를 셔플 저장 |
|
|
223
|
+
| 성능 영향 | 인덱스 활용 가능 | 파티션 pruning 불가 (recursive CTE) |
|
|
224
|
+
|
|
225
|
+
**주의**: 직원 수 10만+ 이상의 대규모 조직에서는 BQ recursive CTE가 느려질 수 있습니다.
|
|
226
|
+
이 경우 `max_recursion_depth` 설정을 확인하고, 필요 시 반복 깊이를 제한하세요.
|
|
227
|
+
|
|
228
|
+
### BQ 최적화 권고
|
|
229
|
+
1. **employees 테이블 클러스터링**: `manager_id`로 클러스터링하면 recursive step의 JOIN 성능 향상
|
|
230
|
+
2. **깊이 제한**: `WHERE depth < 10` 등으로 무한 재귀 방지
|
|
231
|
+
3. **매터리얼라이즈드 뷰**: 조직도가 자주 조회되면 결과를 MV로 캐싱 고려
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bigquery_tuning
|
|
3
|
+
description: BigQuery 900-slot 쿼리 튜닝, anti-pattern 탐지, 비용 최적화, INFORMATION_SCHEMA 참조.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# BigQuery Query Analysis & Optimization Guide
|
|
7
|
+
|
|
8
|
+
BigQuery 쿼리 분석, 튜닝, 비용 최적화 시 참고하는 레퍼런스 가이드입니다.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. INFORMATION_SCHEMA.JOBS 핵심 컬럼
|
|
13
|
+
|
|
14
|
+
데이터는 `creation_time` 기준 파티셔닝, `project_id`와 `user_email`으로 클러스터링. 180일 보관.
|
|
15
|
+
|
|
16
|
+
### 핵심 식별/성능 컬럼
|
|
17
|
+
|
|
18
|
+
| Column | Type | Description |
|
|
19
|
+
|--------|------|-------------|
|
|
20
|
+
| `job_id` | STRING | Unique job identifier |
|
|
21
|
+
| `query` | STRING | SQL text |
|
|
22
|
+
| `total_slot_ms` | INT64 | Total slot-milliseconds consumed |
|
|
23
|
+
| `total_bytes_processed` | INT64 | Bytes processed |
|
|
24
|
+
| `total_bytes_billed` | INT64 | Bytes billed (min 10MB, rounded up to MB) |
|
|
25
|
+
| `cache_hit` | BOOL | Whether results from cache |
|
|
26
|
+
| `job_stages` | RECORD (REPEATED) | Execution stage array |
|
|
27
|
+
| `creation_time` | TIMESTAMP | Job creation time |
|
|
28
|
+
| `start_time` | TIMESTAMP | Execution start |
|
|
29
|
+
| `end_time` | TIMESTAMP | Execution end |
|
|
30
|
+
| `reservation_id` | STRING | Reservation name |
|
|
31
|
+
| `priority` | STRING | INTERACTIVE or BATCH |
|
|
32
|
+
| `referenced_tables` | RECORD (REPEATED) | Tables read |
|
|
33
|
+
| `destination_table` | RECORD | Target table |
|
|
34
|
+
| `statement_type` | STRING | SELECT, INSERT, MERGE, etc. |
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 2. job_stages RECORD 스키마
|
|
39
|
+
|
|
40
|
+
| Field | Type | Description |
|
|
41
|
+
|-------|------|-------------|
|
|
42
|
+
| `id` | INT64 | Stage identifier |
|
|
43
|
+
| `name` | STRING | Human-readable stage name |
|
|
44
|
+
| `slot_ms` | INT64 | Slot-ms used by stage |
|
|
45
|
+
| `records_read` | INT64 | Records read |
|
|
46
|
+
| `records_written` | INT64 | Records written |
|
|
47
|
+
| `shuffle_output_bytes` | INT64 | Bytes written to shuffle |
|
|
48
|
+
| `shuffle_output_bytes_spilled` | INT64 | Bytes spilled to disk |
|
|
49
|
+
| `compute_ms_avg` | INT64 | Avg compute ms per shard |
|
|
50
|
+
| `compute_ms_max` | INT64 | Max compute ms per shard |
|
|
51
|
+
| `wait_ms_avg` | INT64 | Avg wait ms |
|
|
52
|
+
| `wait_ms_max` | INT64 | Max wait ms |
|
|
53
|
+
| `input_stages` | INT64 (REPEATED) | IDs of input stages |
|
|
54
|
+
| `steps` | RECORD (REPEATED) | Operations (kind + substeps) |
|
|
55
|
+
| `parallel_inputs` | INT64 | Number of parallel input segments |
|
|
56
|
+
|
|
57
|
+
**steps sub-record**: `kind` (READ, COMPUTE, AGGREGATE, WRITE, HASH, SORT, JOIN, USER_DEFINED_FUNCTION) + `substeps` (STRING REPEATED)
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 3. Anti-Pattern 탐지 규칙
|
|
62
|
+
|
|
63
|
+
| # | Anti-Pattern | Detection | Severity | Fix |
|
|
64
|
+
|---|-------------|-----------|----------|-----|
|
|
65
|
+
| 1 | `SELECT *` | `SELECT\s+\*` regex | HIGH | 필요 컬럼만 명시 |
|
|
66
|
+
| 2 | Self-join | 같은 테이블이 FROM과 JOIN에 | HIGH | Window/Analytic 함수 또는 PIVOT |
|
|
67
|
+
| 3 | Missing partition filter | 파티션 컬럼 WHERE 조건 없음 | HIGH | 파티션 컬럼 필터 추가 |
|
|
68
|
+
| 4 | `ORDER BY` without `LIMIT` | ORDER BY 있고 LIMIT 없음 | MEDIUM | LIMIT 추가 |
|
|
69
|
+
| 5 | `COUNT(DISTINCT)` high-cardinality | 대규모 데이터에 COUNT(DISTINCT) | MEDIUM | `APPROX_COUNT_DISTINCT()` 사용 |
|
|
70
|
+
| 6 | `NOT IN` subquery | NOT IN + 서브쿼리 | MEDIUM | `NOT EXISTS` 또는 `LEFT JOIN ... IS NULL` |
|
|
71
|
+
| 7 | Cross-join | inequality JOIN 조건 | HIGH | equi-join으로 재구성 |
|
|
72
|
+
| 8 | Repeated CTE | 동일 CTE 2회+ 참조 | LOW | TEMP TABLE로 물리화 |
|
|
73
|
+
| 9 | Leading wildcard `LIKE '%x'` | LIKE 앞에 % | LOW | 가능하면 suffix 검색 회피 |
|
|
74
|
+
| 10 | `UNION` vs `UNION ALL` | 불필요한 중복 제거 | LOW | `UNION ALL` 사용 |
|
|
75
|
+
|
|
76
|
+
참고 도구: `GoogleCloudPlatform/bigquery-antipattern-recognition` (ZetaSQL 기반 AST 분석)
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 4. 비용 추정 공식
|
|
81
|
+
|
|
82
|
+
### On-Demand 가격
|
|
83
|
+
- **$6.25 / TiB** processed (US multi-region)
|
|
84
|
+
- 첫 1 TiB/월 무료
|
|
85
|
+
- 최소 10MB billing, MB 단위 올림
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
cost_usd = (total_bytes_billed / 1024^4) × 6.25
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 900-slot Enterprise Reservation
|
|
92
|
+
- **PAYG**: 900 × 730h × $0.06 = **~$39,420/월**
|
|
93
|
+
- **1-yr**: ~$35,478/월
|
|
94
|
+
- **3-yr**: ~$31,536/월
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
capacity_cost = (total_slot_ms / 3,600,000) × price_per_slot_hour
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### 비용 절감액 계산 (튜닝 시 필수 출력)
|
|
101
|
+
```
|
|
102
|
+
on_demand_saving = (bytes_before - bytes_after) / 1024^4 × 6.25
|
|
103
|
+
monthly_saving = daily_executions × on_demand_saving × 30
|
|
104
|
+
annual_saving = monthly_saving × 12
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 5. Mermaid 다이어그램 템플릿
|
|
110
|
+
|
|
111
|
+
### Color Coding Convention
|
|
112
|
+
|
|
113
|
+
| Color | Hex | Meaning | When to Apply |
|
|
114
|
+
|-------|-----|---------|---------------|
|
|
115
|
+
| Blue | #4285F4 | READ stages | Input/scan |
|
|
116
|
+
| Red | #EA4335 | Bottleneck | slot_ms > 50% of total, or high skew |
|
|
117
|
+
| Orange | #FF6D01 | Data skew | compute_ms_max/avg > 3x |
|
|
118
|
+
| Yellow | #FBBC04 | Shuffle spill | spilled > 0 |
|
|
119
|
+
| Green | #34A853 | WRITE/output | Final output |
|
|
120
|
+
| Gray | #9AA0A6 | Idle/waiting | wait_ratio_avg > 0.5 |
|
|
121
|
+
|
|
122
|
+
### Stage Flowchart 템플릿
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
graph TD
|
|
126
|
+
S0["Stage 0: READ<br/>table_name<br/>records: N<br/>slot_ms: N"]
|
|
127
|
+
S1["Stage 1: HASH JOIN<br/>shuffle: N GB<br/>slot_ms: N"]
|
|
128
|
+
S2["Stage 2: AGGREGATE<br/>GROUP BY col<br/>slot_ms: N"]
|
|
129
|
+
S3["Stage 3: WRITE<br/>output<br/>records: N"]
|
|
130
|
+
|
|
131
|
+
S0 -->|"N rows"| S1
|
|
132
|
+
S1 -->|"N rows"| S2
|
|
133
|
+
S2 -->|"N rows"| S3
|
|
134
|
+
|
|
135
|
+
style S0 fill:#4285F4,color:#fff
|
|
136
|
+
style S1 fill:#EA4335,color:#fff
|
|
137
|
+
style S2 fill:#FBBC04,color:#000
|
|
138
|
+
style S3 fill:#34A853,color:#fff
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### As-Is vs To-Be 비교 레이아웃
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
graph LR
|
|
145
|
+
subgraph "AS-IS (before tuning)"
|
|
146
|
+
A0["READ: full scan<br/>bytes: 500GB"]
|
|
147
|
+
A1["JOIN: shuffle 50GB"]
|
|
148
|
+
A2["OUTPUT"]
|
|
149
|
+
A0 --> A1 --> A2
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
subgraph "TO-BE (after tuning)"
|
|
153
|
+
B0["READ: partition pruned<br/>bytes: 20GB"]
|
|
154
|
+
B1["JOIN: broadcast<br/>shuffle: 0"]
|
|
155
|
+
B2["OUTPUT"]
|
|
156
|
+
B0 --> B1 --> B2
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
style A0 fill:#EA4335,color:#fff
|
|
160
|
+
style A1 fill:#EA4335,color:#fff
|
|
161
|
+
style B0 fill:#34A853,color:#fff
|
|
162
|
+
style B1 fill:#34A853,color:#fff
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 6. 900-Slot 최적화 가이드
|
|
168
|
+
|
|
169
|
+
### 핵심 메트릭
|
|
170
|
+
```
|
|
171
|
+
avg_slots = total_slot_ms / wall_time_ms
|
|
172
|
+
slot_utilization = avg_slots / 900
|
|
173
|
+
contention = period_estimated_runnable_units > 0
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### 최적화 전략
|
|
177
|
+
1. **Slot hog 식별**: `total_slot_ms > 300,000` (5분 이상 slot 소비)
|
|
178
|
+
2. **BATCH priority**: 비긴급 쿼리는 `@{priority: "BATCH"}` 사용
|
|
179
|
+
3. **Stagger batch jobs**: 대형 쿼리 동시 실행 회피
|
|
180
|
+
4. **Partition/Clustering**: 파티션 프루닝 + 클러스터링으로 scan 범위 축소
|
|
181
|
+
5. **Materialized View**: 반복 집계를 MV로 사전 계산
|
|
182
|
+
6. **JOIN 최적화**: broadcast join 유도 (작은 테이블 필터링), skew salting
|
|
183
|
+
|
|
184
|
+
### Slot Pressure 판단 기준
|
|
185
|
+
| Metric | 정상 | 주의 | 위험 |
|
|
186
|
+
|--------|------|------|------|
|
|
187
|
+
| P50 slots | < 450 | 450-720 | > 720 |
|
|
188
|
+
| P99 slots | < 720 | 720-900 | > 900 |
|
|
189
|
+
| Queued units | 0 | 간헐적 | 5분+ 지속 |
|
|
190
|
+
| Spill bytes | 0 | 간헐적 | 상시 |
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 7. 유용한 INFORMATION_SCHEMA 쿼리
|
|
195
|
+
|
|
196
|
+
### Top Expensive Queries (24시간)
|
|
197
|
+
```sql
|
|
198
|
+
SELECT job_id, user_email, query, total_bytes_processed, total_bytes_billed,
|
|
199
|
+
total_slot_ms, TIMESTAMP_DIFF(end_time, start_time, SECOND) AS duration_sec, cache_hit
|
|
200
|
+
FROM `region-us`.INFORMATION_SCHEMA.JOBS
|
|
201
|
+
WHERE creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 24 HOUR)
|
|
202
|
+
AND job_type = 'QUERY' AND state = 'DONE' AND error_result IS NULL
|
|
203
|
+
ORDER BY total_bytes_processed DESC LIMIT 20;
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Slot Pressure (900-slot 초과 여부)
|
|
207
|
+
```sql
|
|
208
|
+
WITH slot_usage AS (
|
|
209
|
+
SELECT TIMESTAMP_TRUNC(period_start, SECOND) AS sec,
|
|
210
|
+
SUM(period_slot_ms) / 1000 AS slots_used,
|
|
211
|
+
MAX(period_estimated_runnable_units) AS runnable_units
|
|
212
|
+
FROM `region-us`.INFORMATION_SCHEMA.JOBS_TIMELINE
|
|
213
|
+
WHERE period_start > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 24 HOUR)
|
|
214
|
+
GROUP BY sec
|
|
215
|
+
)
|
|
216
|
+
SELECT COUNTIF(slots_used > 900) AS seconds_over_900, COUNT(*) AS total_seconds,
|
|
217
|
+
ROUND(COUNTIF(slots_used > 900) / COUNT(*) * 100, 2) AS pct_over_capacity,
|
|
218
|
+
MAX(slots_used) AS peak_slots,
|
|
219
|
+
APPROX_QUANTILES(slots_used, 100)[OFFSET(50)] AS p50,
|
|
220
|
+
APPROX_QUANTILES(slots_used, 100)[OFFSET(90)] AS p90,
|
|
221
|
+
APPROX_QUANTILES(slots_used, 100)[OFFSET(99)] AS p99
|
|
222
|
+
FROM slot_usage;
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Skew Detection
|
|
226
|
+
```sql
|
|
227
|
+
SELECT job_id, stage.name, stage.id, stage.slot_ms,
|
|
228
|
+
stage.compute_ms_max, stage.compute_ms_avg,
|
|
229
|
+
SAFE_DIVIDE(stage.compute_ms_max, NULLIF(stage.compute_ms_avg, 0)) AS skew_ratio,
|
|
230
|
+
stage.shuffle_output_bytes_spilled
|
|
231
|
+
FROM `region-us`.INFORMATION_SCHEMA.JOBS, UNNEST(job_stages) AS stage
|
|
232
|
+
WHERE creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 24 HOUR)
|
|
233
|
+
AND job_type = 'QUERY' AND state = 'DONE' AND total_slot_ms > 60000
|
|
234
|
+
ORDER BY skew_ratio DESC LIMIT 50;
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Anomaly Detection (Z-score)
|
|
238
|
+
```sql
|
|
239
|
+
WITH query_patterns AS (
|
|
240
|
+
SELECT REGEXP_REPLACE(REGEXP_REPLACE(query, r"'[^']*'", "'?'"), r'\b\d+\b', '?') AS template,
|
|
241
|
+
total_slot_ms, TIMESTAMP_DIFF(end_time, start_time, SECOND) AS duration_sec, job_id
|
|
242
|
+
FROM `region-us`.INFORMATION_SCHEMA.JOBS
|
|
243
|
+
WHERE creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
|
|
244
|
+
AND job_type = 'QUERY' AND state = 'DONE' AND error_result IS NULL
|
|
245
|
+
),
|
|
246
|
+
stats AS (
|
|
247
|
+
SELECT template, AVG(total_slot_ms) AS avg_slot_ms, STDDEV(total_slot_ms) AS std_slot_ms,
|
|
248
|
+
AVG(duration_sec) AS avg_dur, STDDEV(duration_sec) AS std_dur
|
|
249
|
+
FROM query_patterns GROUP BY template HAVING COUNT(*) >= 5
|
|
250
|
+
)
|
|
251
|
+
SELECT p.job_id, p.duration_sec, s.avg_dur,
|
|
252
|
+
ROUND((p.duration_sec - s.avg_dur) / NULLIF(s.std_dur, 0), 2) AS dur_z,
|
|
253
|
+
ROUND((p.total_slot_ms - s.avg_slot_ms) / NULLIF(s.std_slot_ms, 0), 2) AS slot_z
|
|
254
|
+
FROM query_patterns p JOIN stats s ON p.template = s.template
|
|
255
|
+
WHERE ABS((p.total_slot_ms - s.avg_slot_ms) / NULLIF(s.std_slot_ms, 0)) > 3
|
|
256
|
+
ORDER BY slot_z DESC LIMIT 20;
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## 8. 추가 기능 가이드
|
|
262
|
+
|
|
263
|
+
### Schema Analysis
|
|
264
|
+
```sql
|
|
265
|
+
-- 테이블 크기/행 수
|
|
266
|
+
SELECT table_name, total_rows,
|
|
267
|
+
ROUND(total_logical_bytes / POW(1024, 3), 2) AS size_gb,
|
|
268
|
+
ROUND(total_physical_bytes / NULLIF(total_logical_bytes, 0), 2) AS compression_ratio
|
|
269
|
+
FROM `project.dataset`.INFORMATION_SCHEMA.TABLE_STORAGE
|
|
270
|
+
ORDER BY total_logical_bytes DESC;
|
|
271
|
+
|
|
272
|
+
-- 컬럼 메타데이터 (파티션/클러스터 확인)
|
|
273
|
+
SELECT column_name, data_type, is_partitioning_column, clustering_ordinal_position
|
|
274
|
+
FROM `project.dataset`.INFORMATION_SCHEMA.COLUMNS
|
|
275
|
+
WHERE table_name = 'target_table' ORDER BY ordinal_position;
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Data Lineage (테이블 의존관계)
|
|
279
|
+
```sql
|
|
280
|
+
SELECT ref.project_id, ref.dataset_id, ref.table_id,
|
|
281
|
+
COUNT(*) AS query_count, COUNT(DISTINCT user_email) AS users
|
|
282
|
+
FROM `region-us`.INFORMATION_SCHEMA.JOBS, UNNEST(referenced_tables) AS ref
|
|
283
|
+
WHERE creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
|
|
284
|
+
AND job_type = 'QUERY' AND state = 'DONE'
|
|
285
|
+
GROUP BY 1, 2, 3 ORDER BY query_count DESC LIMIT 30;
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Dry-Run 비용 사전 추정 (Python)
|
|
289
|
+
```python
|
|
290
|
+
from google.cloud import bigquery
|
|
291
|
+
client = bigquery.Client()
|
|
292
|
+
job_config = bigquery.QueryJobConfig(dry_run=True, use_query_cache=False)
|
|
293
|
+
query_job = client.query("SELECT ...", job_config=job_config)
|
|
294
|
+
bytes_processed = query_job.total_bytes_processed
|
|
295
|
+
cost_estimate = (bytes_processed / (1024**4)) * 6.25
|
|
296
|
+
print(f"Estimated cost: ${cost_estimate:.4f}")
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## ⚠️ 필수 출력 규칙
|
|
302
|
+
|
|
303
|
+
**모든 튜닝/오류수정 응답에는 반드시 ```mermaid 다이어그램을 포함하세요.**
|
|
304
|
+
- 튜닝: AS-IS vs TO-BE 실행 흐름 비교 (위 템플릿 참조)
|
|
305
|
+
- 오류 수정: 에러 발생 흐름 → 수정 후 정상 흐름
|
|
306
|
+
- 위 Color Coding Convention을 반드시 적용하세요.
|
|
307
|
+
- 다이어그램 없는 응답은 불완전한 응답입니다.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: classification_evaluation
|
|
3
|
+
description: 'Classification Evaluation Template. 이런 요청에 쓴다: classification, 분류, confusion matrix, 혼동행렬, roc'
|
|
4
|
+
---
|
|
5
|
+
## Classification Evaluation Template
|
|
6
|
+
1. **Confusion Matrix**: `confusion_matrix()` → `ConfusionMatrixDisplay`
|
|
7
|
+
2. **Classification Report**: `classification_report()` (precision, recall, F1)
|
|
8
|
+
3. **ROC Curve**: `roc_curve()` → `RocCurveDisplay` with AUC score
|
|
9
|
+
4. **Precision-Recall Curve**: For imbalanced datasets
|
|
10
|
+
5. **Cross-Validation**: Stratified K-Fold to ensure class balance
|
|
11
|
+
6. **Error Analysis**: Examine misclassified samples for patterns
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: clustering_analysis
|
|
3
|
+
description: 'Clustering Analysis Template. 이런 요청에 쓴다: clustering, k-means, dbscan, silhouette, 군집, 클러스터링'
|
|
4
|
+
---
|
|
5
|
+
## Clustering Analysis Template
|
|
6
|
+
1. **Data Scaling**: `StandardScaler()` — critical for distance-based methods
|
|
7
|
+
2. **Optimal K**: Elbow method (`inertia_`) + Silhouette score (`silhouette_score()`)
|
|
8
|
+
3. **Algorithm Selection**: K-Means, DBSCAN, Hierarchical — based on data shape
|
|
9
|
+
4. **Fit & Predict**: `labels = model.fit_predict(X_scaled)`
|
|
10
|
+
5. **Evaluation**: Silhouette, Calinski-Harabasz, Davies-Bouldin scores
|
|
11
|
+
6. **Visualization**: PCA/t-SNE 2D scatter colored by cluster labels
|
|
12
|
+
7. **Cluster Profiling**: Aggregate stats per cluster, identify distinguishing features
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: comprehensive_eda
|
|
3
|
+
description: 'EDA Workflow Template. 이런 요청에 쓴다: eda, 탐색적 데이터 분석, exploratory, 데이터 탐색, 데이터 분석'
|
|
4
|
+
---
|
|
5
|
+
## EDA Workflow Template
|
|
6
|
+
1. **Data Overview**: `df.shape`, `df.info()`, `df.describe()`, `df.dtypes`
|
|
7
|
+
2. **Missing Values**: `df.isnull().sum()`, visualize with `msno.matrix(df)`
|
|
8
|
+
3. **Distributions**: Histograms for numerical, value_counts for categorical
|
|
9
|
+
4. **Correlations**: `df.corr()` heatmap with `sns.heatmap()`
|
|
10
|
+
5. **Outliers**: Box plots, IQR method, z-score analysis
|
|
11
|
+
6. **Target Analysis**: Distribution, class balance, relationship with features
|