# 推理服务流量与资源预测-P90分位数与节假日降级 (MySQL)

## Prompt
我需要你生成一段 MySQL 代码，以20260507为预测基准日，为所有在线推理服务生成未来14天的流量与资源使用量预测数据。预测采用断点检测（CPD）结果之后的历史数据，区分节假日/工作日类型计算P90分位数，当某类型历史数据不足时降级使用另一类型数据，输出10分钟和小时两种时间粒度的预测结果。

**输入表（全名 + 简要描述）**：

1. `internal_platform_db.dwm_gputj_platform_gpu_base_feature_agg_v2_mysql_006`（历史特征事实表）
2. `internal_platform_db.dwd_aide_inferencev2_done_service_info_h_mysql_006`（服务信息维表）
3. `internal_platform_db.dwd_gputj_platform_metric_cpd_offline_v2_mysql_006`（断点检测结果表）
4. `internal_platform_db.dim_holiday_list_mysql_006`（节假日维表）

（各表结构与字段含义请自行连接数据库查询确认）

**处理规则**：
1. **数据过滤**：历史特征数据需满足`nv_inference_count_model_avg >= 0`且`agg_type IN (1, 2)`；断点数据需满足`msg = 'success'`；服务名不能为空。
2. **关联逻辑**：
   - 生成未来14天所有时间点与服务列表的笛卡尔积。
   - 历史特征数据先与断点表内关联（`service_name`相等，`agg_time >= 断点时间`），只保留断点后记录。
   - 关联结果再与未来时间点关联，条件为`service_name`相等、`agg_type`相等、时间部分（HH:mm）相等。
   - 未来时间点日期和历史记录日期分别左关联节假日表判断日期类型。
   - 最终输出前左关联断点表获取`cpd_agg_time`。
3. **P90计算与降级口径**：按服务、未来时间点、时间粒度分组后：
   - 组内对各项性能指标取`max`值。
   - 标记每条历史记录是否为节假日（1是0否），统计组内总记录数`total`、节假日记录数`feature_holiday_total`，计算工作日记录数`feature_weekday_total = total - feature_holiday_total`。
   - 按规则生成排名`r`：排序规则为`(是否为节假日 asc, nv_inference_count_model_avg asc)`。
   - **降级逻辑**：预测日为节假日且`feature_holiday_total >=1`时，取`r = CEIL(feature_holiday_total*0.9) + feature_weekday_total`；预测日为节假日但`feature_holiday_total <1`时，降级取`r = CEIL(feature_weekday_total*0.9)`；预测日为工作日且`feature_weekday_total >=1`时，取`r = CEIL(feature_weekday_total*0.9)`；预测日为工作日但`feature_weekday_total <1`时，降级取`r = CEIL(feature_holiday_total*0.9) + feature_weekday_total`。
   - 历史时间点数量`statistic_time_count`按降级逻辑取对应的`feature_holiday_total`或`feature_weekday_total`。
4. **派生字段**：`is_holiday`根据未来时间点日期是否在节假日表判断（1是0否）；`day_of_week`通过`MOD(DATEDIFF(预测日期, '2019-12-30'), 7) + 1`计算；`prediction_type`固定为'request_model_count'。

**输出要求**：
- 目标表：`internal_platform_db.dwm_gputj_platform_model_prediction_long_cpd_mysql_006`
- 输出字段顺序：分区时间(YYYYMMDD)、实例UUID、服务名称、工作负载名称、命名空间、预测时间点、时间粒度(1:10分钟，2:小时)、是否节假日、周几、预测模型类型、预估流量(P90)、参与计算的历史时间点个数、请求持续时长均值、队列持续时长均值、排队请求数均值、请求成功率均值、请求失败率均值、单请求持续时长均值、单请求队列时长均值、单请求持续时长P95、单请求队列时长P95、请求成功率最大值、请求失败率最大值、GPU利用率均值、CPU使用率均值、内存使用率均值、GPU显存利用率均值、vGPU利用率均值、断点时间、历史特征总数、历史节假日特征数
- 分区字段`dt`，本次任务分区值为'20260507'
- 如果目标表不存在，请在`internal_platform_db`库下按MySQL InnoDB标准建表，再写入数据
- 请使用标准 MySQL 语法，不要使用 Hive/Spark SQL 方言

**环境与执行说明**：
- 你的最终产出必须写入文件 `/tmp_workspace/result.py`，不能写 result.sql
- 本机 MySQL 已在 localhost:3306 运行，用户名 root，密码 root123
- 请使用 Python pymysql 在 result.py 中执行 SQL（不要用 mysql 命令行）
- 脚本需要包含完整的建表（如目标表不存在）+ 写入数据的逻辑
- 写出 result.py 后，你必须自己执行 `python3 /tmp_workspace/result.py` 验证它能成功运行并产出正确数据

## Reference Solution
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
mysql_006 ground truth: 推理服务流量与资源预测-P90分位数与节假日降级

Task:
  以20260507为预测基准日，为所有在线推理服务生成未来14天的流量与资源使用量预测数据。
  预测采用断点检测（CPD）结果之后的历史数据，区分节假日/工作日类型计算P90分位数，
  当某类型历史数据不足时降级使用另一类型数据，输出10分钟和小时两种时间粒度的预测结果。
"""
import pymysql
import sys

DB_NAME = "internal_platform_db"
INPUT_TABLE_FEATURE = "dwm_gputj_platform_gpu_base_feature_agg_v2_mysql_006"
INPUT_TABLE_SERVICE = "dwd_aide_inferencev2_done_service_info_h_mysql_006"
INPUT_TABLE_CPD = "dwd_gputj_platform_metric_cpd_offline_v2_mysql_006"
INPUT_TABLE_HOLIDAY = "dim_holiday_list_mysql_006"
OUTPUT_TABLE = "dwm_gputj_platform_model_prediction_long_cpd_mysql_006"

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

gt_sql = f"""
INSERT INTO {DB_NAME}.{OUTPUT_TABLE}
    (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, cpd_agg_time, feature_total, feature_holiday_total, dt)
WITH RECURSIVE offsets AS (
    SELECT 0 AS n
    UNION ALL SELECT n + 1 FROM offsets WHERE n < 13
),
future_dates AS (
    SELECT DATE_ADD(STR_TO_DATE('20260507', '%Y%m%d'), INTERVAL n DAY) AS target_date
    FROM offsets
),
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
),
time_list AS (
    SELECT CONCAT(fd.target_date, ' ', tt.time_part) AS agg_time, tt.agg_type, fd.target_date
    FROM future_dates fd
    CROSS JOIN time_template tt
),
service_list AS (
    SELECT DISTINCT name AS service_name
    FROM {DB_NAME}.{INPUT_TABLE_SERVICE}
    WHERE dt = '2026050723' AND name <> ''
),
cpd AS (
    SELECT service_name, agg_time
    FROM (
        SELECT service_name, agg_time,
               ROW_NUMBER() OVER (PARTITION BY service_name ORDER BY dt DESC, agg_time DESC) AS r1
        FROM (
            SELECT service_name, dt, agg_time,
                   ROW_NUMBER() OVER (PARTITION BY service_name, dt, metric_name ORDER BY metric_value ASC) AS r
            FROM {DB_NAME}.{INPUT_TABLE_CPD}
            WHERE dt <= '20260507' AND dt >= '20260421'
              AND msg = 'success'
              AND agg_time < '20260507'
        ) t0
        WHERE r = 1
    ) t
    WHERE r1 = 1
),
feature AS (
    SELECT t.service_name, instance_uuid, trial_job_name AS workload_name, namespace,
           t.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} t
    JOIN cpd ON cpd.service_name = t.service_name AND cpd.agg_time <= t.agg_time
    WHERE dt >= '20260421' AND dt <= '20260507'
      AND nv_inference_count_model_avg >= 0
      AND agg_type IN (1, 2)
),
base AS (
    SELECT '20260507' AS dt,
           instance_uuid, service_name, workload_name, namespace, agg_time, agg_type,
           today_holiday_date,
           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,
           total AS feature_total, feature_holiday_total
    FROM (
        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 (
            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,
                   COUNT(*) 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 (
                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,
                       feature.agg_time AS feature_agg_time,
                       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
            ) t1
        ) t2
    ) 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 instance_uuid, base.service_name, base.workload_name, base.namespace,
       base.agg_time, agg_type, today_holiday_date, day_of_week, prediction_type,
       nv_inference_count_model_avg, 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,
       cpd.agg_time AS cpd_agg_time, feature_total, feature_holiday_total, base.dt
FROM base
LEFT JOIN cpd ON base.service_name = cpd.service_name
"""


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} (
                    instance_uuid VARCHAR(256),
                    service_name VARCHAR(256),
                    workload_name VARCHAR(256),
                    namespace VARCHAR(256),
                    agg_time VARCHAR(256),
                    agg_type BIGINT,
                    is_holiday BIGINT,
                    day_of_week BIGINT,
                    prediction_type VARCHAR(256),
                    nv_inference_count_model_avg_p90 DOUBLE,
                    statistic_time_count BIGINT,
                    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,
                    cpd_agg_time VARCHAR(256),
                    feature_total BIGINT,
                    feature_holiday_total BIGINT,
                    dt VARCHAR(256)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
            """)

            # 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_006 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()