-- data-ana ClickHouse DDL:5 宽表建表脚本 -- 对齐 02-architecture-design.md §3 DDL 设计 -- 引擎:ReplacingMergeTree(幂等消费保证)+ MergeTree(历史快照) -- 使用方式:clickhouse-client --multiquery < scripts/clickhouse_ddl.sql CREATE DATABASE IF NOT EXISTS edu_analytics; -- §3.1 学生学情宽表 CREATE TABLE IF NOT EXISTS edu_analytics.student_dashboard_view ( student_id String, class_id String, exam_id String, subject_id String, score Float64, rank_in_class UInt32, knowledge_point_id String, mastery_level Float32, error_count UInt32, last_updated DateTime64(3, 'UTC') ) ENGINE = ReplacingMergeTree(last_updated) PARTITION BY toYYYYMM(last_updated) ORDER BY (student_id, exam_id, knowledge_point_id) SETTINGS index_granularity = 8192; -- §3.2 学生错题本 CREATE TABLE IF NOT EXISTS edu_analytics.student_errors ( student_id String, question_id String, knowledge_point_id String, error_count UInt32, last_error_time DateTime64(3, 'UTC'), content String ) ENGINE = ReplacingMergeTree(last_error_time) PARTITION BY toYYYYMM(last_error_time) ORDER BY (student_id, question_id); -- §3.3 知识点掌握度历史快照 CREATE TABLE IF NOT EXISTS edu_analytics.mastery_snapshot ( student_id String, knowledge_point_id String, subject_id String, mastery_level Float32, calculated_at DateTime64(3, 'UTC'), calculation_method LowCardinality(String) ) ENGINE = MergeTree PARTITION BY toYYYYMM(calculated_at) ORDER BY (student_id, knowledge_point_id, calculated_at); -- §3.4 AI 用量计费记录 CREATE TABLE IF NOT EXISTS edu_analytics.ai_usage_log ( request_id String, user_id String, provider LowCardinality(String), model LowCardinality(String), prompt_tokens UInt32, completion_tokens UInt32, total_tokens UInt32, latency_ms UInt32, success Boolean, cost_cents UInt32, occurred_at DateTime64(3, 'UTC') ) ENGINE = ReplacingMergeTree(occurred_at) PARTITION BY toYYYYMM(occurred_at) ORDER BY (request_id); -- §3.5 学生考勤记录 CREATE TABLE IF NOT EXISTS edu_analytics.attendance_logs ( student_id String, class_id String, attendance_date Date, status LowCardinality(String), recorded_by String, remark String DEFAULT '', occurred_at DateTime64(3, 'UTC') ) ENGINE = ReplacingMergeTree(occurred_at) PARTITION BY toYYYYMM(attendance_date) ORDER BY (student_id, class_id, attendance_date);