# GPU Inference Platform P90 Traffic Forecast (Holiday/Workday Differentiation) (MySQL)

## Prompt
I need you to generate a MySQL script that produces 14-day traffic and resource usage forecasts (P90 percentile) for each service on the GPU inference platform, differentiating between holidays and workdays, with mutual fallback when historical samples are insufficient, and outputting results at both 10-minute and hourly time granularities.

**Business Background and Objective**: The GPU inference platform needs to forecast traffic and resource usage for each service over the next 14 days. The forecast is based on P90 percentile values from historical data, with differentiation between holidays and workdays. When historical samples for one category are insufficient, the other category is used as a fallback. The output includes forecast results at both 10-minute and hourly time granularities.

**Input Tables (full name + brief description)**:
- `internal_platform_db.dwm_gputj_platform_gpu_base_feature_agg_v2_mysql_005` (GPU feature aggregation fact table)
- `internal_platform_db.dwd_aide_inferencev2_done_service_info_h_mysql_005` (service list dimension table)
- `internal_platform_db.dim_holiday_list_mysql_005` (holiday dimension table)

(Please connect to the database and query to confirm the table structures and field semantics.)

**Processing Rules**:
1. **Fact table data range**: Take partitions between `'20260420'` and `'20260507'`, excluding the anomalous period from `'20260504'` to `'20260504'`; traffic value `nv_inference_count_model_avg` >= 0; `agg_type` is 1 or 2.
2. **Time point template**: Extracted from the fact table partitions `'20260502'` to `'20260507'` (exclusive).
3. **Join logic**:
   - Cartesian product of the service list with all time points over the next 14 days (at 10-minute and hourly granularities).
   - Join with the historical fact table on join keys: `service_name`, `agg_type`, and the hour-minute portion of the time point.
   - Left join the holiday dimension table twice: once for the prediction date and once for the historical data date.
4. **Derived fields**:
   - `is_holiday`: Whether the prediction date is a holiday (1/0).
   - `day_of_week`: Day of the week for the prediction date (1–7).
   - `prediction_type`: Fixed as `'request_model_count'`.
   - `statistic_time_count`: Number of historical time points used in the forecast, computed using the holiday/workday mutual fallback logic.
   - P90 forecast fields: Based on the prediction day type (holiday/workday), take the P90 value of each metric from the corresponding historical data, with fallback to the other type when insufficient.
   - `workload_name`, `namespace`, etc.: Take the maximum value per service from the historical fact table.

**Output Requirements**:
- **Output table**: `internal_platform_db.dws_gputj_platform_model_prediction_long_p90_mysql_005`
- **Output fields (in order)**: `dt`, `instance_uuid`, `service_name`, `workload_name`, `namespace`, `agg_time`, `agg_type`, `is_holiday`, `day_of_week`, `prediction_type`, `nv_inference_count_model_avg_p90`, `statistic_time_count`, `nv_inference_request_duration_ms_model_avg`, `nv_inference_queue_duration_ms_model_avg`, `num_queued_reqs_model_avg`, `nv_inference_request_success_model_avg`, `nv_inference_request_failure_model_avg`, `nv_inference_request_duration_ms_perreq_avg`, `nv_inference_queue_duration_ms_perreq_avg`, `nv_inference_request_duration_ms_perreq_p95`, `nv_inference_queue_duration_ms_perreq_p95`, `nv_inference_request_success_model_max`, `nv_inference_request_failure_model_max`, `DCGM_FI_DEV_GPU_UTIL_pod_avg`, `k8s_container_bs_rate_cpu_core_used_request_pod_avg`, `k8s_container_rate_mem_working_set_request_pod_avg`, `k8s_dcgm_fi_dev_fb_util_pod_avg`, `k8s_container_vgpu_gpu_util_pod_avg`
- **Write method**: DELETE + INSERT or TRUNCATE + INSERT INTO ... SELECT
- If the target table does not exist, first create it using standard MySQL InnoDB format, then write the data
- Use standard MySQL syntax; do not use Hive/Spark SQL dialects

**Environment and Execution Notes**:
- Your final output must be written to the file `/tmp_workspace/result.py`, not `result.sql`
- The local MySQL is running at localhost:3306, username `root`, password `root123`
- Use Python `pymysql` in `result.py` to execute the SQL (do not use the `mysql` command-line tool)
- The script must include complete table creation (if the target table does not exist) and data writing logic
- After writing `result.py`, you must execute `python3 /tmp_workspace/result.py` yourself to verify that it runs successfully and produces correct data

## Reference Solution
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
mysql_005 ground truth: GPU推理平台P90流量预估

Task:
  Generate P90 predictions for GPU inference platform services
  over the next 14 days, distinguishing holidays vs weekdays,
  with fallback logic when historical samples are insufficient.
"""
import pymysql
import sys

DB_NAME = "internal_platform_db"
INPUT_TABLE_FEATURE = "dwm_gputj_platform_gpu_base_feature_agg_v2_mysql_005"
INPUT_TABLE_SERVICE = "dwd_aide_inferencev2_done_service_info_h_mysql_005"
INPUT_TABLE_HOLIDAY = "dim_holiday_list_mysql_005"
OUTPUT_TABLE = "dws_gputj_platform_model_prediction_long_p90_mysql_005"

MYSQL_CONFIG = {
    "host": "localhost",
    "port": 3306,
    "user": "root",
    "password": "root123",
    "charset": "utf8mb4",
}

gt_sql = f"""
INSERT INTO {DB_NAME}.{OUTPUT_TABLE}
    (dt, instance_uuid, service_name, workload_name, namespace, agg_time, agg_type,
     is_holiday, day_of_week, prediction_type,
     nv_inference_count_model_avg_p90, statistic_time_count,
     nv_inference_request_duration_ms_model_avg, nv_inference_queue_duration_ms_model_avg,
     num_queued_reqs_model_avg, nv_inference_request_success_model_avg,
     nv_inference_request_failure_model_avg, nv_inference_request_duration_ms_perreq_avg,
     nv_inference_queue_duration_ms_perreq_avg, nv_inference_request_duration_ms_perreq_p95,
     nv_inference_queue_duration_ms_perreq_p95, nv_inference_request_success_model_max,
     nv_inference_request_failure_model_max, DCGM_FI_DEV_GPU_UTIL_pod_avg,
     k8s_container_bs_rate_cpu_core_used_request_pod_avg,
     k8s_container_rate_mem_working_set_request_pod_avg,
     k8s_dcgm_fi_dev_fb_util_pod_avg, k8s_container_vgpu_gpu_util_pod_avg)
WITH
-- Generate 14 future dates starting from 2026-05-07
future_dates AS (
    SELECT DATE_ADD(STR_TO_DATE('20260507', '%Y%m%d'), INTERVAL offset DAY) AS target_date
    FROM (
        SELECT 0 AS offset UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
        UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7
        UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11
        UNION ALL SELECT 12 UNION ALL SELECT 13
    ) offsets
),
-- Extract time template (hour/10-min granularity time points)
time_template AS (
    SELECT SUBSTRING_INDEX(agg_time, ' ', -1) AS time_part, agg_type
    FROM {DB_NAME}.{INPUT_TABLE_FEATURE}
    WHERE dt >= '20260502' AND dt < '20260507' AND agg_time > ''
    GROUP BY SUBSTRING_INDEX(agg_time, ' ', -1), agg_type
),
-- Generate 14 days x all time points
time_list AS (
    SELECT CONCAT(DATE_FORMAT(fd.target_date, '%Y-%m-%d'), ' ', tt.time_part) AS agg_time,
           tt.agg_type, fd.target_date
    FROM future_dates fd
    CROSS JOIN time_template tt
),
-- Get distinct service names
service_list AS (
    SELECT DISTINCT name AS service_name
    FROM {DB_NAME}.{INPUT_TABLE_SERVICE}
    WHERE dt = IF('2026050723' >= '2025101512', '2026050723', '2025101512') AND name <> ''
),
-- Filter feature data
feature AS (
    SELECT service_name, instance_uuid,
           trial_job_name AS workload_name, namespace, agg_time, agg_type,
           nv_inference_count_model_avg,
           nv_inference_request_duration_ms_model_avg,
           nv_inference_queue_duration_ms_model_avg,
           num_queued_reqs_model_avg,
           nv_inference_request_success_model_avg,
           nv_inference_request_failure_model_avg,
           nv_inference_request_duration_ms_perreq_avg,
           nv_inference_queue_duration_ms_perreq_avg,
           nv_inference_request_duration_ms_perreq_p95,
           nv_inference_queue_duration_ms_perreq_p95,
           nv_inference_request_success_model_max,
           nv_inference_request_failure_model_max,
           dcgm_fi_dev_gpu_util_pod_avg,
           k8s_container_bs_rate_cpu_core_used_request_pod_avg,
           k8s_container_rate_mem_working_set_request_pod_avg,
           k8s_dcgm_fi_dev_fb_util_pod_avg,
           k8s_container_vgpu_gpu_util_pod_avg
    FROM {DB_NAME}.{INPUT_TABLE_FEATURE}
    WHERE dt >= '20260420' AND dt <= '20260507'
      AND (dt < '20260504' OR dt > '20260504')
      AND nv_inference_count_model_avg >= 0
      AND agg_type IN (1, 2)
),
-- Core join + aggregation
t1 AS (
    SELECT time_list.agg_time,
           feature.agg_type,
           MAX(feature.instance_uuid) AS instance_uuid,
           feature.service_name,
           MAX(feature.workload_name) AS workload_name,
           MAX(feature.namespace) AS namespace,
           MAX(CASE WHEN holiday_today.holiday_date > '' THEN 1 ELSE 0 END) AS today_holiday_date,
           MAX(feature.nv_inference_count_model_avg) AS nv_inference_count_model_avg,
           MAX(feature.nv_inference_request_duration_ms_model_avg) AS nv_inference_request_duration_ms_model_avg,
           MAX(feature.nv_inference_queue_duration_ms_model_avg) AS nv_inference_queue_duration_ms_model_avg,
           MAX(feature.num_queued_reqs_model_avg) AS num_queued_reqs_model_avg,
           MAX(feature.nv_inference_request_success_model_avg) AS nv_inference_request_success_model_avg,
           MAX(feature.nv_inference_request_failure_model_avg) AS nv_inference_request_failure_model_avg,
           MAX(feature.nv_inference_request_duration_ms_perreq_avg) AS nv_inference_request_duration_ms_perreq_avg,
           MAX(feature.nv_inference_queue_duration_ms_perreq_avg) AS nv_inference_queue_duration_ms_perreq_avg,
           MAX(feature.nv_inference_request_duration_ms_perreq_p95) AS nv_inference_request_duration_ms_perreq_p95,
           MAX(feature.nv_inference_queue_duration_ms_perreq_p95) AS nv_inference_queue_duration_ms_perreq_p95,
           MAX(feature.nv_inference_request_success_model_max) AS nv_inference_request_success_model_max,
           MAX(feature.nv_inference_request_failure_model_max) AS nv_inference_request_failure_model_max,
           MAX(feature.dcgm_fi_dev_gpu_util_pod_avg) AS dcgm_fi_dev_gpu_util_pod_avg,
           MAX(feature.k8s_container_bs_rate_cpu_core_used_request_pod_avg) AS k8s_container_bs_rate_cpu_core_used_request_pod_avg,
           MAX(feature.k8s_container_rate_mem_working_set_request_pod_avg) AS k8s_container_rate_mem_working_set_request_pod_avg,
           MAX(feature.k8s_dcgm_fi_dev_fb_util_pod_avg) AS k8s_dcgm_fi_dev_fb_util_pod_avg,
           MAX(feature.k8s_container_vgpu_gpu_util_pod_avg) AS k8s_container_vgpu_gpu_util_pod_avg,
           MAX(CASE WHEN holiday_feature.holiday_date > '' THEN 1 ELSE 0 END) AS feature_holiday_date
    FROM service_list
    CROSS JOIN time_list
    JOIN feature
      ON service_list.service_name = feature.service_name
     AND time_list.agg_type = feature.agg_type
     AND SUBSTRING_INDEX(time_list.agg_time, ' ', -1) = SUBSTRING_INDEX(feature.agg_time, ' ', -1)
    LEFT JOIN {DB_NAME}.{INPUT_TABLE_HOLIDAY} holiday_today
      ON SUBSTRING_INDEX(time_list.agg_time, ' ', 1) = holiday_today.holiday_date
    LEFT JOIN {DB_NAME}.{INPUT_TABLE_HOLIDAY} holiday_feature
      ON SUBSTRING_INDEX(feature.agg_time, ' ', 1) = holiday_feature.holiday_date
    GROUP BY time_list.agg_time, feature.agg_time, feature.agg_type, feature.service_name
),
t2 AS (
    SELECT *,
           ROW_NUMBER() OVER (PARTITION BY service_name, agg_time, agg_type ORDER BY feature_holiday_date ASC, nv_inference_count_model_avg ASC) AS r,
           SUM(1) OVER (PARTITION BY service_name, agg_time, agg_type) AS total,
           SUM(feature_holiday_date) OVER (PARTITION BY service_name, agg_time, agg_type) AS feature_holiday_total
    FROM t1
),
t3 AS (
    SELECT *,
           total - feature_holiday_total AS feature_weekday_total,
           CEIL((total - feature_holiday_total) * 0.9) AS feature_weekday_index,
           CEIL(feature_holiday_total * 0.9) + (total - feature_holiday_total) AS feature_holiday_index
    FROM t2
),
base AS (
    SELECT '20260507' AS dt,
           instance_uuid,
           service_name,
           workload_name,
           namespace,
           agg_time,
           agg_type,
           today_holiday_date,
           -- MySQL: DAYOFWEEK returns 1=Sunday..7=Saturday; we need 1=Monday..7=Sunday
           MOD(DATEDIFF(SUBSTRING_INDEX(agg_time, ' ', 1), '2019-12-30'), 7) + 1 AS day_of_week,
           'request_model_count' AS prediction_type,
           nv_inference_count_model_avg,
           CASE
               WHEN today_holiday_date = 1 AND feature_holiday_total > 0 THEN feature_holiday_total
               WHEN today_holiday_date = 1 AND feature_holiday_total = 0 THEN feature_weekday_total
               WHEN today_holiday_date = 0 AND feature_weekday_total > 0 THEN feature_weekday_total
               WHEN today_holiday_date = 0 AND feature_weekday_total = 0 THEN feature_holiday_total
           END AS statistic_time_count,
           nv_inference_request_duration_ms_model_avg,
           nv_inference_queue_duration_ms_model_avg,
           num_queued_reqs_model_avg,
           nv_inference_request_success_model_avg,
           nv_inference_request_failure_model_avg,
           nv_inference_request_duration_ms_perreq_avg,
           nv_inference_queue_duration_ms_perreq_avg,
           nv_inference_request_duration_ms_perreq_p95,
           nv_inference_queue_duration_ms_perreq_p95,
           nv_inference_request_success_model_max,
           nv_inference_request_failure_model_max,
           dcgm_fi_dev_gpu_util_pod_avg,
           k8s_container_bs_rate_cpu_core_used_request_pod_avg,
           k8s_container_rate_mem_working_set_request_pod_avg,
           k8s_dcgm_fi_dev_fb_util_pod_avg,
           k8s_container_vgpu_gpu_util_pod_avg
    FROM t3
    WHERE r = CASE
                 WHEN today_holiday_date = 1 AND feature_holiday_total >= 1 THEN feature_holiday_index
                 WHEN today_holiday_date = 1 AND feature_holiday_total < 1 THEN feature_weekday_index
                 WHEN today_holiday_date = 0 AND feature_weekday_total >= 1 THEN feature_weekday_index
                 WHEN today_holiday_date = 0 AND feature_weekday_total < 1 THEN feature_holiday_index
             END
)
SELECT dt, instance_uuid, service_name, workload_name, namespace, agg_time, agg_type,
       today_holiday_date AS is_holiday, day_of_week, prediction_type,
       nv_inference_count_model_avg AS nv_inference_count_model_avg_p90, statistic_time_count,
       nv_inference_request_duration_ms_model_avg, nv_inference_queue_duration_ms_model_avg,
       num_queued_reqs_model_avg, nv_inference_request_success_model_avg,
       nv_inference_request_failure_model_avg, nv_inference_request_duration_ms_perreq_avg,
       nv_inference_queue_duration_ms_perreq_avg, nv_inference_request_duration_ms_perreq_p95,
       nv_inference_queue_duration_ms_perreq_p95, nv_inference_request_success_model_max,
       nv_inference_request_failure_model_max, dcgm_fi_dev_gpu_util_pod_avg,
       k8s_container_bs_rate_cpu_core_used_request_pod_avg,
       k8s_container_rate_mem_working_set_request_pod_avg,
       k8s_dcgm_fi_dev_fb_util_pod_avg, k8s_container_vgpu_gpu_util_pod_avg
FROM base
"""


def main():
    conn = pymysql.connect(**MYSQL_CONFIG)

    try:
        with conn.cursor() as cur:
            # Ensure output table exists
            cur.execute(f"""
                CREATE TABLE IF NOT EXISTS {DB_NAME}.{OUTPUT_TABLE} (
                    `dt` VARCHAR(256) COMMENT '分区时间(YYYYMMDD)',
                    `instance_uuid` VARCHAR(256) COMMENT '实例UUID',
                    `service_name` VARCHAR(256) COMMENT '服务名称',
                    `workload_name` VARCHAR(256) COMMENT '工作负载名称',
                    `namespace` VARCHAR(256) COMMENT '命名空间',
                    `agg_time` VARCHAR(256) COMMENT '预测时间点',
                    `agg_type` BIGINT COMMENT '1:10分钟粒度，2:小时粒度',
                    `is_holiday` BIGINT COMMENT '是否节假日:0-1',
                    `day_of_week` BIGINT COMMENT '星期几:1-7',
                    `prediction_type` VARCHAR(256) COMMENT '预测模型',
                    `nv_inference_count_model_avg_p90` DOUBLE COMMENT '预估流量P90',
                    `statistic_time_count` BIGINT COMMENT '参与预估的时间点个数',
                    `nv_inference_request_duration_ms_model_avg` DOUBLE,
                    `nv_inference_queue_duration_ms_model_avg` DOUBLE,
                    `num_queued_reqs_model_avg` DOUBLE,
                    `nv_inference_request_success_model_avg` DOUBLE,
                    `nv_inference_request_failure_model_avg` DOUBLE,
                    `nv_inference_request_duration_ms_perreq_avg` DOUBLE,
                    `nv_inference_queue_duration_ms_perreq_avg` DOUBLE,
                    `nv_inference_request_duration_ms_perreq_p95` DOUBLE,
                    `nv_inference_queue_duration_ms_perreq_p95` DOUBLE,
                    `nv_inference_request_success_model_max` DOUBLE,
                    `nv_inference_request_failure_model_max` DOUBLE,
                    `DCGM_FI_DEV_GPU_UTIL_pod_avg` DOUBLE,
                    `k8s_container_bs_rate_cpu_core_used_request_pod_avg` DOUBLE,
                    `k8s_container_rate_mem_working_set_request_pod_avg` DOUBLE,
                    `k8s_dcgm_fi_dev_fb_util_pod_avg` DOUBLE,
                    `k8s_container_vgpu_gpu_util_pod_avg` DOUBLE
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
            """)

            # Truncate + insert
            cur.execute(f"TRUNCATE TABLE {DB_NAME}.{OUTPUT_TABLE}")
            cur.execute(gt_sql)

        conn.commit()

        # Verify row count
        with conn.cursor() as cur:
            cur.execute(f"SELECT COUNT(*) FROM {DB_NAME}.{OUTPUT_TABLE}")
            count = cur.fetchone()[0]
        print(f"mysql_005 ground_truth done: {count} rows written to output table")
    except Exception as e:
        print(f"ground_truth error: {e}", file=sys.stderr)
        conn.rollback()
        sys.exit(1)
    finally:
        conn.close()


if __name__ == "__main__":
    main()