Files
banban/talkingq-url/mysql/mysql.md
2026-03-24 15:04:36 +08:00

24 KiB
Raw Blame History

TalkingQ MySQL 查询手册

数据库概览

TalkingQ 使用 MySQL 8.0 作为数据库后端,存储设备配置、角色信息和会话数据。本文档提供了数据库结构和常用查询操作的参考。

连接信息

数据库名称: talkingq
用户名: talkingq
密码: 在 .env 或 .env.prod 文件中配置的 MYSQL_PASSWORD
主机: localhost (本地开发) 或 mysql (Docker环境)
端口: 3306

连接数据库

# 本地开发环境
mysql -u talkingq -p talkingq

# Docker环境中
sudo docker compose exec -it mysql mysql -u talkingq -p talkingq

表结构

device_configs - 设备配置表

存储设备的角色选择和语言偏好等配置。

字段名 类型 描述
id INT 主键,自增
device_id VARCHAR(64) 设备ID唯一索引
selected_role_key VARCHAR(64) 选中的角色键
preferred_language VARCHAR(10) 首选语言代码
last_update_time FLOAT 最后更新时间戳
created_at DATETIME 创建时间
updated_at DATETIME 更新时间

conversation_histories - 对话历史表

存储设备的对话历史记录和角色信息。

字段名 类型 描述
id INT 主键,自增
device_id VARCHAR(64) 设备ID索引
role_key VARCHAR(64) 角色键,索引
last_interaction_time FLOAT 最后交互时间戳
created_at DATETIME 创建时间
updated_at DATETIME 更新时间

conversation_messages - 对话消息表

存储对话的具体消息内容。

字段名 类型 描述
id INT 主键,自增
conversation_id INT 关联的对话历史ID外键
is_user BOOLEAN 是否为用户消息
content TEXT 消息内容
timestamp FLOAT 消息时间戳
created_at DATETIME 创建时间
updated_at DATETIME 更新时间

roles - 角色表

存储系统中可用的角色定义。

字段名 类型 描述
id INT 主键,自增
role_key VARCHAR(64) 角色键名,唯一索引
name VARCHAR(128) 角色名称
description TEXT 角色描述
content TEXT 系统提示内容
default_language VARCHAR(10) 默认语言代码
asr_provider VARCHAR(64) ASR服务提供商
llm_provider VARCHAR(64) LLM服务提供商
tts_provider VARCHAR(64) TTS服务提供商
competitive_llm_mode BOOLEAN 是否启用竞争模式
volcano_model_id VARCHAR(64) Volcano模型ID
volcano_voice_type VARCHAR(64) Volcano音色类型
tencent_voice_type VARCHAR(64) 腾讯音色类型
aliyun_voice_name VARCHAR(64) 阿里云音色名称
url VARCHAR(255) 资源URL路径
homophones JSON 同音词列表
enabled BOOLEAN 是否启用
created_at DATETIME 创建时间
updated_at DATETIME 更新时间

role_languages - 角色语言表

存储角色的多语言配置。

字段名 类型 描述
id INT 主键,自增
role_id INT 关联的角色ID外键
language_code VARCHAR(10) 语言代码
name VARCHAR(128) 该语言下的角色名称
content TEXT 该语言下的系统提示内容
asr_provider VARCHAR(64) 该语言的ASR服务提供商
llm_provider VARCHAR(64) 该语言的LLM服务提供商
tts_provider VARCHAR(64) 该语言的TTS服务提供商
volcano_voice_type VARCHAR(64) 该语言的Volcano音色类型
tencent_voice_type VARCHAR(64) 该语言的腾讯音色类型
aliyun_voice_name VARCHAR(64) 该语言的阿里云音色名称
url VARCHAR(255) 该语言的资源URL路径
created_at DATETIME 创建时间
updated_at DATETIME 更新时间

device_auth - 设备认证表

存储设备认证信息,用于验证设备身份。

字段名 类型 描述
id INT 主键,自增
device_id VARCHAR(64) 设备ID唯一索引
serial_number VARCHAR(64) 设备序列号
is_active BOOLEAN 是否活跃
created_at DATETIME 创建时间
updated_at DATETIME 更新时间

常用查询示例

设备配置查询

查询所有设备配置

SELECT * FROM device_configs;

查询特定设备的配置

SELECT * FROM device_configs WHERE device_id = '设备ID';

查询使用特定角色的设备

SELECT * FROM device_configs WHERE selected_role_key = '角色键名';

查询使用特定语言的设备

SELECT * FROM device_configs WHERE preferred_language = '语言代码';

查询最近更新的设备配置

SELECT * FROM device_configs
ORDER BY last_update_time DESC
LIMIT 10;

对话历史查询

查询特定设备的所有对话历史

SELECT * FROM conversation_histories WHERE device_id = '设备ID';

查询特定设备和角色的对话历史

SELECT * FROM conversation_histories 
WHERE device_id = '设备ID' AND role_key = '角色键名';

查询最近交互的对话历史

SELECT * FROM conversation_histories 
ORDER BY last_interaction_time DESC 
LIMIT 10;

查询一段时间内的对话历史

SELECT * FROM conversation_histories 
WHERE last_interaction_time BETWEEN UNIX_TIMESTAMP('2023-01-01') AND UNIX_TIMESTAMP('2023-12-31')
ORDER BY last_interaction_time DESC;

对话消息查询

查询特定对话的所有消息

SELECT * FROM conversation_messages 
WHERE conversation_id = 对话ID
ORDER BY timestamp ASC;

查询特定对话的用户消息

SELECT * FROM conversation_messages 
WHERE conversation_id = 对话ID AND is_user = TRUE
ORDER BY timestamp ASC;

查询特定对话的助手回复

SELECT * FROM conversation_messages 
WHERE conversation_id = 对话ID AND is_user = FALSE
ORDER BY timestamp ASC;

查询包含特定关键词的消息

SELECT * FROM conversation_messages 
WHERE content LIKE '%关键词%'
ORDER BY timestamp DESC;

查询最近的消息记录

SELECT cm.*, ch.device_id, ch.role_key 
FROM conversation_messages cm
JOIN conversation_histories ch ON cm.conversation_id = ch.id
ORDER BY cm.timestamp DESC
LIMIT 20;

角色表查询

查询所有启用的角色

SELECT * FROM roles WHERE enabled = TRUE;

查询特定角色的详细信息

SELECT * FROM roles WHERE role_key = '角色键名';

查询使用特定服务提供商的角色

SELECT * FROM roles WHERE llm_provider = 'Volcano';
-- 或
SELECT * FROM roles WHERE tts_provider = 'Tencent';
-- 或
SELECT * FROM roles WHERE asr_provider = 'Aliyun';

查询角色的同音词列表

SELECT role_key, homophones FROM roles WHERE homophones IS NOT NULL;

查询启用竞争模式的角色

SELECT * FROM roles WHERE competitive_llm_mode = TRUE;

角色语言表查询

查询特定角色的所有语言配置

SELECT rl.* FROM role_languages rl
JOIN roles r ON rl.role_id = r.id
WHERE r.role_key = '角色键名';

查询特定语言的所有角色配置

SELECT r.role_key, r.name, rl.* FROM role_languages rl
JOIN roles r ON rl.role_id = r.id
WHERE rl.language_code = '语言代码';

查询特定角色特定语言的配置

SELECT rl.* FROM role_languages rl
JOIN roles r ON rl.role_id = r.id
WHERE r.role_key = '角色键名' AND rl.language_code = '语言代码';

查询支持多语言的角色列表

SELECT r.role_key, r.name, COUNT(rl.id) as language_count
FROM roles r
JOIN role_languages rl ON r.id = rl.role_id
GROUP BY r.id
HAVING language_count > 1
ORDER BY language_count DESC;

设备认证查询

查询所有已认证设备

SELECT * FROM device_auth WHERE is_active = TRUE;

查询特定设备的认证信息

SELECT * FROM device_auth WHERE device_id = '设备ID';

查询最近添加的设备认证

SELECT * FROM device_auth
ORDER BY created_at DESC
LIMIT 10;

多表联合查询

查询特定设备的所有消息及对应的角色

SELECT cm.*, ch.role_key 
FROM conversation_messages cm 
JOIN conversation_histories ch ON cm.conversation_id = ch.id 
WHERE ch.device_id = '设备ID'
ORDER BY cm.timestamp ASC;

查询特定设备使用特定角色的所有对话内容

SELECT cm.*, ch.role_key, ch.last_interaction_time 
FROM conversation_messages cm 
JOIN conversation_histories ch ON cm.conversation_id = ch.id 
WHERE ch.device_id = '设备ID' AND ch.role_key = '角色键名'
ORDER BY cm.timestamp ASC;

查询所有设备的最新一条消息

SELECT ch.device_id, ch.role_key, cm.content, cm.timestamp 
FROM conversation_histories ch 
JOIN conversation_messages cm ON ch.id = cm.conversation_id 
WHERE cm.id = (
    SELECT MAX(cm2.id) 
    FROM conversation_messages cm2
    WHERE cm2.conversation_id = ch.id
);

查询设备当前使用的角色详细信息

SELECT dc.device_id, r.* 
FROM device_configs dc
JOIN roles r ON dc.selected_role_key = r.role_key
WHERE dc.device_id = '设备ID';

查询设备对话中使用的所有角色

SELECT DISTINCT ch.device_id, ch.role_key, r.name, r.description
FROM conversation_histories ch
JOIN roles r ON ch.role_key = r.role_key
WHERE ch.device_id = '设备ID';

查询设备认证状态与当前配置信息

SELECT da.device_id, da.serial_number, da.is_active, 
       dc.selected_role_key, dc.preferred_language, dc.last_update_time
FROM device_auth da
LEFT JOIN device_configs dc ON da.device_id = dc.device_id
ORDER BY da.created_at DESC;

高级统计查询

统计每个角色的使用情况

SELECT selected_role_key, COUNT(*) as device_count 
FROM device_configs 
GROUP BY selected_role_key
ORDER BY device_count DESC;

统计每种语言的使用情况

SELECT preferred_language, COUNT(*) as language_count 
FROM device_configs 
WHERE preferred_language IS NOT NULL
GROUP BY preferred_language
ORDER BY language_count DESC;

统计每个设备的对话数量

SELECT device_id, COUNT(*) as conversation_count 
FROM conversation_histories 
GROUP BY device_id
ORDER BY conversation_count DESC;

统计每个角色的对话数量

SELECT role_key, COUNT(*) as conversation_count 
FROM conversation_histories 
GROUP BY role_key
ORDER BY conversation_count DESC;

统计消息量最多的对话

SELECT ch.id, ch.device_id, ch.role_key, COUNT(cm.id) as message_count 
FROM conversation_histories ch 
JOIN conversation_messages cm ON ch.id = cm.conversation_id 
GROUP BY ch.id, ch.device_id, ch.role_key
ORDER BY message_count DESC
LIMIT 10;

统计最活跃的设备

SELECT device_id, COUNT(DISTINCT role_key) as roles_used, 
       COUNT(*) as total_conversations,
       MAX(last_interaction_time) as last_active
FROM conversation_histories 
GROUP BY device_id
ORDER BY total_conversations DESC
LIMIT 10;

统计各语言下的角色数量

SELECT rl.language_code, COUNT(DISTINCT r.id) as role_count
FROM role_languages rl
JOIN roles r ON rl.role_id = r.id
GROUP BY rl.language_code
ORDER BY role_count DESC;

统计近期设备活跃度

SELECT 
    DATE(FROM_UNIXTIME(last_interaction_time)) as date,
    COUNT(DISTINCT device_id) as active_devices
FROM conversation_histories
WHERE last_interaction_time > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY))
GROUP BY date
ORDER BY date DESC;

统计各TTS提供商的使用情况

SELECT 
    CASE 
        WHEN volcano_voice_type IS NOT NULL THEN 'Volcano'
        WHEN tencent_voice_type IS NOT NULL THEN 'Tencent'
        WHEN aliyun_voice_name IS NOT NULL THEN 'Aliyun'
        ELSE 'Unknown'
    END as tts_provider,
    COUNT(*) as role_count
FROM roles
GROUP BY tts_provider
ORDER BY role_count DESC;

统计设备认证与使用情况

SELECT 
    COUNT(da.id) as total_devices,
    SUM(CASE WHEN da.is_active = TRUE THEN 1 ELSE 0 END) as active_devices,
    SUM(CASE WHEN dc.id IS NOT NULL THEN 1 ELSE 0 END) as configured_devices,
    SUM(CASE WHEN ch.device_id IS NOT NULL THEN 1 ELSE 0 END) as devices_with_conversations
FROM device_auth da
LEFT JOIN device_configs dc ON da.device_id = dc.device_id
LEFT JOIN (SELECT DISTINCT device_id FROM conversation_histories) ch ON da.device_id = ch.device_id;

数据分析查询

对话内容分析

查询用户问题平均长度

SELECT ch.role_key, AVG(LENGTH(cm.content)) as avg_length 
FROM conversation_messages cm 
JOIN conversation_histories ch ON cm.conversation_id = ch.id 
WHERE cm.is_user = TRUE
GROUP BY ch.role_key;

查询助手回答平均长度

SELECT ch.role_key, AVG(LENGTH(cm.content)) as avg_length 
FROM conversation_messages cm 
JOIN conversation_histories ch ON cm.conversation_id = ch.id 
WHERE cm.is_user = FALSE
GROUP BY ch.role_key;

查询用户消息长度分布

SELECT 
    CASE 
        WHEN LENGTH(content) < 50 THEN '极短 (<50)'
        WHEN LENGTH(content) BETWEEN 50 AND 100 THEN '短 (50-100)'
        WHEN LENGTH(content) BETWEEN 101 AND 200 THEN '中 (101-200)'
        WHEN LENGTH(content) BETWEEN 201 AND 500 THEN '长 (201-500)'
        ELSE '极长 (>500)'
    END as message_length_category,
    COUNT(*) as message_count
FROM conversation_messages
WHERE is_user = TRUE
GROUP BY message_length_category
ORDER BY 
    CASE message_length_category
        WHEN '极短 (<50)' THEN 1
        WHEN '短 (50-100)' THEN 2
        WHEN '中 (101-200)' THEN 3
        WHEN '长 (201-500)' THEN 4
        ELSE 5
    END;

查询不同角色对话完成时间统计

SELECT ch.role_key, 
       COUNT(*) as conversation_count,
       AVG(MAX(cm.timestamp) - MIN(cm.timestamp)) as avg_duration
FROM conversation_histories ch
JOIN conversation_messages cm ON ch.id = cm.conversation_id
GROUP BY ch.role_key
HAVING conversation_count > 5
ORDER BY avg_duration DESC;

查询不同语言的平均对话长度

SELECT dc.preferred_language, 
       COUNT(DISTINCT ch.id) as conversation_count,
       AVG(cm_count.msg_count) as avg_messages_per_conversation
FROM device_configs dc
JOIN conversation_histories ch ON dc.device_id = ch.device_id
JOIN (
    SELECT conversation_id, COUNT(*) as msg_count
    FROM conversation_messages
    GROUP BY conversation_id
) cm_count ON ch.id = cm_count.conversation_id
WHERE dc.preferred_language IS NOT NULL
GROUP BY dc.preferred_language
HAVING conversation_count > 3
ORDER BY avg_messages_per_conversation DESC;

查询包含特定关键词的对话

SELECT ch.id, ch.device_id, ch.role_key, 
       MAX(ch.last_interaction_time) as conversation_time,
       GROUP_CONCAT(DISTINCT CASE WHEN cm.is_user = TRUE THEN cm.content ELSE NULL END SEPARATOR '\n') as user_messages,
       GROUP_CONCAT(DISTINCT CASE WHEN cm.is_user = FALSE THEN cm.content ELSE NULL END SEPARATOR '\n') as assistant_messages
FROM conversation_histories ch
JOIN conversation_messages cm ON ch.id = cm.conversation_id
WHERE cm.content LIKE '%关键词%'
GROUP BY ch.id, ch.device_id, ch.role_key
ORDER BY conversation_time DESC;

用户行为分析

查询用户平均会话时长趋势

SELECT 
    DATE(FROM_UNIXTIME(ch.last_interaction_time)) as date,
    AVG(
        MAX(cm.timestamp) - MIN(cm.timestamp)
    ) as avg_session_duration
FROM conversation_histories ch
JOIN conversation_messages cm ON ch.id = cm.conversation_id
WHERE ch.last_interaction_time > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY))
GROUP BY date
ORDER BY date;

查询每日活跃用户数和对话量

SELECT 
    DATE(FROM_UNIXTIME(last_interaction_time)) as date,
    COUNT(DISTINCT device_id) as active_users,
    COUNT(*) as conversations
FROM conversation_histories
WHERE last_interaction_time > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY))
GROUP BY date
ORDER BY date DESC;

查询设备的首次使用时间和最后使用时间

SELECT 
    device_id,
    MIN(created_at) as first_use,
    FROM_UNIXTIME(MAX(last_interaction_time)) as last_use,
    DATEDIFF(FROM_UNIXTIME(MAX(last_interaction_time)), MIN(created_at)) as days_between
FROM conversation_histories
GROUP BY device_id
ORDER BY days_between DESC;

查询用户连续活跃天数

WITH daily_activity AS (
    SELECT 
        device_id, 
        DATE(FROM_UNIXTIME(last_interaction_time)) as activity_date
    FROM conversation_histories
    GROUP BY device_id, activity_date
)
SELECT 
    device_id,
    COUNT(*) as active_days,
    MIN(activity_date) as first_active_day,
    MAX(activity_date) as last_active_day,
    DATEDIFF(MAX(activity_date), MIN(activity_date)) + 1 as day_span,
    COUNT(*) / (DATEDIFF(MAX(activity_date), MIN(activity_date)) + 1) as activity_ratio
FROM daily_activity
GROUP BY device_id
HAVING day_span > 7
ORDER BY active_days DESC, activity_ratio DESC;

管理操作

备份数据库

# 在Docker环境外执行
docker exec -it talkingq-mysql-1 mysqldump -u root -p talkingq > talkingq_backup.sql

# 或使用本地MySQL客户端
mysqldump -h localhost -u talkingq -p talkingq > talkingq_backup.sql

恢复数据库

# 在Docker环境外执行
cat talkingq_backup.sql | docker exec -i talkingq-mysql-1 mysql -u root -p talkingq

# 或使用本地MySQL客户端
mysql -h localhost -u talkingq -p talkingq < talkingq_backup.sql

备份特定表

# 仅备份设备配置表
docker exec -it talkingq-mysql-1 mysqldump -u root -p talkingq device_configs > device_configs_backup.sql

# 仅备份角色表和角色语言表
docker exec -it talkingq-mysql-1 mysqldump -u root -p talkingq roles role_languages > roles_backup.sql

# 仅备份对话历史和消息表
docker exec -it talkingq-mysql-1 mysqldump -u root -p talkingq conversation_histories conversation_messages > conversations_backup.sql

# 备份设备认证表
docker exec -it talkingq-mysql-1 mysqldump -u root -p talkingq device_auth > device_auth_backup.sql

删除过期记录

-- 删除长期未使用的设备配置
DELETE FROM device_configs 
WHERE last_update_time < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 90 DAY));

-- 删除3个月前的对话历史
DELETE ch, cm
FROM conversation_histories ch
LEFT JOIN conversation_messages cm ON ch.id = cm.conversation_id
WHERE ch.last_interaction_time < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 3 MONTH));

-- 将90天内未被任何设备使用的角色标记为禁用
UPDATE roles r
SET enabled = FALSE
WHERE r.role_key NOT IN (
    SELECT DISTINCT selected_role_key 
    FROM device_configs
    WHERE last_update_time > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 90 DAY))
) AND r.role_key NOT IN (
    SELECT DISTINCT role_key 
    FROM conversation_histories
    WHERE last_interaction_time > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 90 DAY))
);

-- 清理已停用设备的认证记录
UPDATE device_auth
SET is_active = FALSE
WHERE device_id NOT IN (
    SELECT DISTINCT device_id 
    FROM conversation_histories
    WHERE last_interaction_time > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 180 DAY))
);

角色管理

-- 添加新角色(基本信息)
INSERT INTO roles (role_key, name, description, content, default_language, enabled)
VALUES ('new_role', '新角色', '新角色的描述', '系统提示内容', 'zh', TRUE);

-- 为角色添加语言配置
INSERT INTO role_languages (role_id, language_code, name, content)
VALUES (
    (SELECT id FROM roles WHERE role_key = 'new_role'),
    'en',
    'New Role',
    'System prompt content in English'
);

-- 复制角色
INSERT INTO roles (
    role_key, name, description, content, default_language, 
    asr_provider, llm_provider, tts_provider, competitive_llm_mode,
    volcano_model_id, volcano_voice_type, tencent_voice_type, aliyun_voice_name,
    url, homophones, enabled
)
SELECT 
    CONCAT(role_key, '_copy'), CONCAT(name, ' (复制)'), description, content, default_language,
    asr_provider, llm_provider, tts_provider, competitive_llm_mode,
    volcano_model_id, volcano_voice_type, tencent_voice_type, aliyun_voice_name,
    url, homophones, enabled
FROM roles
WHERE role_key = '要复制的角色键名';

数据库优化

优化表

OPTIMIZE TABLE device_configs;
OPTIMIZE TABLE conversation_histories;
OPTIMIZE TABLE conversation_messages;
OPTIMIZE TABLE roles;
OPTIMIZE TABLE role_languages;
OPTIMIZE TABLE device_auth;

分析表

ANALYZE TABLE device_configs;
ANALYZE TABLE conversation_histories;
ANALYZE TABLE conversation_messages;
ANALYZE TABLE roles;
ANALYZE TABLE role_languages;
ANALYZE TABLE device_auth;

检查表

CHECK TABLE device_configs;
CHECK TABLE conversation_histories;
CHECK TABLE conversation_messages;
CHECK TABLE roles;
CHECK TABLE role_languages;
CHECK TABLE device_auth;

添加索引

-- 为对话历史表添加联合索引
CREATE INDEX idx_device_role ON conversation_histories(device_id, role_key);

-- 为角色语言表添加联合索引
CREATE INDEX idx_role_language ON role_languages(role_id, language_code);

-- 为消息表添加时间戳索引,优化时间范围查询
CREATE INDEX idx_message_timestamp ON conversation_messages(timestamp);

-- 为设备认证表添加索引
CREATE INDEX idx_device_auth_active ON device_auth(is_active);

监控查询性能

-- 查看慢查询日志状态
SHOW VARIABLES LIKE 'slow_query%';

-- 查看当前运行的查询
SHOW PROCESSLIST;

-- 终止执行时间过长的查询
KILL QUERY 线程ID;

数据库维护脚本示例

以下是一个可以添加到cron任务的脚本示例用于定期清理过期数据和优化表

#!/bin/bash
# 文件名: /home/ubuntu/TalkingQ_URL/scripts/db_maintenance.sh

# 数据库连接参数
DB_USER="talkingq"
DB_PASS="您的密码"
DB_NAME="talkingq"
DB_HOST="mysql"

# 日志文件
LOG_FILE="/home/ubuntu/TalkingQ_URL/logs/db_maintenance.log"

echo "===== $(date) 开始数据库维护 =====" >> $LOG_FILE

# 删除3个月前的对话历史
echo "清理旧对话历史..." >> $LOG_FILE
docker exec -i talkingq-mysql-1 mysql -u$DB_USER -p$DB_PASS $DB_NAME << EOF
DELETE ch, cm
FROM conversation_histories ch
LEFT JOIN conversation_messages cm ON ch.id = cm.conversation_id
WHERE ch.last_interaction_time < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 3 MONTH));
EOF

# 优化表
echo "优化数据库表..." >> $LOG_FILE
docker exec -i talkingq-mysql-1 mysql -u$DB_USER -p$DB_PASS $DB_NAME << EOF
OPTIMIZE TABLE conversation_histories, conversation_messages, device_configs;
EOF

echo "===== $(date) 数据库维护完成 =====" >> $LOG_FILE