-- nl-video-api 数据库性能优化脚本 -- 执行前请备份数据库 -- ================================ -- 1. 索引优化 -- ================================ -- 用户表索引优化 ALTER TABLE `user` ADD INDEX `idx_username` (`username`); ALTER TABLE `user` ADD INDEX `idx_phone` (`phone`); ALTER TABLE `user` ADD INDEX `idx_email` (`email`); ALTER TABLE `user` ADD INDEX `idx_status_vip` (`status`, `vip_level`); ALTER TABLE `user` ADD INDEX `idx_created_at` (`created_at`); ALTER TABLE `user` ADD INDEX `idx_last_login` (`last_login_at`); -- 管理员表索引优化 ALTER TABLE `admin` ADD INDEX `idx_username` (`username`); ALTER TABLE `admin` ADD INDEX `idx_email` (`email`); ALTER TABLE `admin` ADD INDEX `idx_status` (`status`); -- 影片表索引优化 ALTER TABLE `movie` ADD INDEX `idx_title` (`title`); ALTER TABLE `movie` ADD INDEX `idx_type_category` (`type`, `category_id`); ALTER TABLE `movie` ADD INDEX `idx_year` (`year`); ALTER TABLE `movie` ADD INDEX `idx_country` (`country`); ALTER TABLE `movie` ADD INDEX `idx_status` (`status`); ALTER TABLE `movie` ADD INDEX `idx_rating` (`rating`); ALTER TABLE `movie` ADD INDEX `idx_created_at` (`created_at`); ALTER TABLE `movie` ADD INDEX `idx_updated_at` (`updated_at`); -- 剧集表索引优化 ALTER TABLE `episode` ADD INDEX `idx_movie_id` (`movie_id`); ALTER TABLE `episode` ADD INDEX `idx_episode_number` (`episode_number`); ALTER TABLE `episode` ADD INDEX `idx_status` (`status`); -- 分类表索引优化 ALTER TABLE `category` ADD INDEX `idx_parent_id` (`parent_id`); ALTER TABLE `category` ADD INDEX `idx_sort` (`sort`); ALTER TABLE `category` ADD INDEX `idx_status` (`status`); -- 角色表索引优化 ALTER TABLE `role` ADD INDEX `idx_code` (`code`); ALTER TABLE `role` ADD INDEX `idx_level` (`level`); ALTER TABLE `role` ADD INDEX `idx_status` (`status`); -- 权限表索引优化 ALTER TABLE `permission` ADD INDEX `idx_parent_id` (`parent_id`); ALTER TABLE `permission` ADD INDEX `idx_type` (`type`); ALTER TABLE `permission` ADD INDEX `idx_status` (`status`); -- 角色权限关联表索引优化 ALTER TABLE `role_permission` ADD INDEX `idx_role_id` (`role_id`); ALTER TABLE `role_permission` ADD INDEX `idx_permission_id` (`permission_id`); -- ================================ -- 2. 表结构优化 -- ================================ -- 优化用户表字段类型 ALTER TABLE `user` MODIFY COLUMN `balance` DECIMAL(10,2) DEFAULT 0.00 COMMENT '余额'; ALTER TABLE `user` MODIFY COLUMN `points` INT UNSIGNED DEFAULT 0 COMMENT '积分'; ALTER TABLE `user` MODIFY COLUMN `vip_level` TINYINT UNSIGNED DEFAULT 0 COMMENT 'VIP等级'; -- 优化影片表字段类型 ALTER TABLE `movie` MODIFY COLUMN `rating` DECIMAL(3,1) DEFAULT 0.0 COMMENT '评分'; ALTER TABLE `movie` MODIFY COLUMN `duration` SMALLINT UNSIGNED DEFAULT 0 COMMENT '时长(分钟)'; ALTER TABLE `movie` MODIFY COLUMN `total_episodes` SMALLINT UNSIGNED DEFAULT 0 COMMENT '总集数'; -- 优化角色表字段类型 ALTER TABLE `role` MODIFY COLUMN `level` TINYINT UNSIGNED DEFAULT 1 COMMENT '角色等级'; ALTER TABLE `role` MODIFY COLUMN `sort` SMALLINT UNSIGNED DEFAULT 0 COMMENT '排序'; -- ================================ -- 3. 分区优化(适用于大数据量) -- ================================ -- 用户表按注册时间分区(年度分区) -- 注意:分区需要在表创建时定义,这里仅作为参考 /* ALTER TABLE `user` PARTITION BY RANGE (YEAR(created_at)) ( PARTITION p2023 VALUES LESS THAN (2024), PARTITION p2024 VALUES LESS THAN (2025), PARTITION p2025 VALUES LESS THAN (2026), PARTITION p_future VALUES LESS THAN MAXVALUE ); */ -- ================================ -- 4. 查询优化视图 -- ================================ -- 创建用户统计视图 CREATE OR REPLACE VIEW `v_user_stats` AS SELECT COUNT(*) as total_users, COUNT(CASE WHEN status = 1 THEN 1 END) as active_users, COUNT(CASE WHEN vip_level > 0 THEN 1 END) as vip_users, COUNT(CASE WHEN DATE(created_at) = CURDATE() THEN 1 END) as today_new_users, AVG(balance) as avg_balance, SUM(balance) as total_balance FROM `user`; -- 创建影片统计视图 CREATE OR REPLACE VIEW `v_movie_stats` AS SELECT COUNT(*) as total_movies, COUNT(CASE WHEN type = 1 THEN 1 END) as movie_count, COUNT(CASE WHEN type = 2 THEN 1 END) as tv_series_count, COUNT(CASE WHEN status = 1 THEN 1 END) as published_count, AVG(rating) as avg_rating, COUNT(CASE WHEN DATE(created_at) = CURDATE() THEN 1 END) as today_new_movies FROM `movie`; -- 创建热门影片视图 CREATE OR REPLACE VIEW `v_popular_movies` AS SELECT m.id, m.title, m.type, m.rating, m.year, c.name as category_name FROM `movie` m LEFT JOIN `category` c ON m.category_id = c.id WHERE m.status = 1 ORDER BY m.rating DESC, m.created_at DESC; -- ================================ -- 5. 存储过程优化 -- ================================ -- 用户余额更新存储过程 DELIMITER // CREATE PROCEDURE `sp_update_user_balance`( IN p_user_id INT, IN p_amount DECIMAL(10,2), IN p_type TINYINT, IN p_remark VARCHAR(255) ) BEGIN DECLARE v_current_balance DECIMAL(10,2) DEFAULT 0; DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; RESIGNAL; END; START TRANSACTION; -- 获取当前余额 SELECT balance INTO v_current_balance FROM `user` WHERE id = p_user_id FOR UPDATE; -- 检查余额是否足够(扣款时) IF p_type = 2 AND v_current_balance < ABS(p_amount) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '余额不足'; END IF; -- 更新余额 IF p_type = 1 THEN UPDATE `user` SET balance = balance + p_amount WHERE id = p_user_id; ELSE UPDATE `user` SET balance = balance - ABS(p_amount) WHERE id = p_user_id; END IF; -- 记录余额变动日志(如果有日志表的话) -- INSERT INTO `balance_log` (user_id, amount, type, remark, created_at) -- VALUES (p_user_id, p_amount, p_type, p_remark, NOW()); COMMIT; END // DELIMITER ; -- VIP升级存储过程 DELIMITER // CREATE PROCEDURE `sp_upgrade_user_vip`( IN p_user_id INT, IN p_vip_level TINYINT, IN p_days INT ) BEGIN DECLARE v_current_vip_expire DATETIME; DECLARE v_new_vip_expire DATETIME; DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; RESIGNAL; END; START TRANSACTION; -- 获取当前VIP到期时间 SELECT vip_expire_at INTO v_current_vip_expire FROM `user` WHERE id = p_user_id; -- 计算新的到期时间 IF v_current_vip_expire IS NULL OR v_current_vip_expire < NOW() THEN SET v_new_vip_expire = DATE_ADD(NOW(), INTERVAL p_days DAY); ELSE SET v_new_vip_expire = DATE_ADD(v_current_vip_expire, INTERVAL p_days DAY); END IF; -- 更新用户VIP信息 UPDATE `user` SET vip_level = p_vip_level, vip_expire_at = v_new_vip_expire, updated_at = NOW() WHERE id = p_user_id; COMMIT; END // DELIMITER ; -- ================================ -- 6. 数据清理和维护 -- ================================ -- 清理过期的VIP用户 UPDATE `user` SET vip_level = 0 WHERE vip_expire_at < NOW() AND vip_level > 0; -- 清理软删除的数据(超过30天) DELETE FROM `movie` WHERE deleted_at IS NOT NULL AND deleted_at < DATE_SUB(NOW(), INTERVAL 30 DAY); DELETE FROM `user` WHERE deleted_at IS NOT NULL AND deleted_at < DATE_SUB(NOW(), INTERVAL 30 DAY); -- ================================ -- 7. 性能监控查询 -- ================================ -- 查看慢查询日志状态 SHOW VARIABLES LIKE 'slow_query_log%'; SHOW VARIABLES LIKE 'long_query_time'; -- 查看索引使用情况 SELECT TABLE_SCHEMA, TABLE_NAME, INDEX_NAME, CARDINALITY, SUB_PART, PACKED, NULLABLE, INDEX_TYPE FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = 'nl_video_db' ORDER BY TABLE_NAME, INDEX_NAME; -- 查看表大小和行数 SELECT TABLE_NAME, TABLE_ROWS, ROUND(((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024), 2) AS 'Size(MB)', ROUND((DATA_LENGTH / 1024 / 1024), 2) AS 'Data(MB)', ROUND((INDEX_LENGTH / 1024 / 1024), 2) AS 'Index(MB)' FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'nl_video_db' ORDER BY (DATA_LENGTH + INDEX_LENGTH) DESC; -- ================================ -- 8. 配置优化建议 -- ================================ /* MySQL配置优化建议(my.cnf): [mysqld] # 基础配置 default-storage-engine = InnoDB character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci # 内存配置 innodb_buffer_pool_size = 1G # 设置为物理内存的70-80% innodb_log_file_size = 256M innodb_log_buffer_size = 16M key_buffer_size = 256M max_connections = 500 thread_cache_size = 50 # 查询缓存 query_cache_type = 1 query_cache_size = 256M query_cache_limit = 2M # 慢查询日志 slow_query_log = 1 slow_query_log_file = /var/log/mysql/slow.log long_query_time = 2 # InnoDB配置 innodb_flush_log_at_trx_commit = 2 innodb_flush_method = O_DIRECT innodb_file_per_table = 1 innodb_open_files = 400 # 临时表配置 tmp_table_size = 256M max_heap_table_size = 256M # 排序和连接配置 sort_buffer_size = 2M join_buffer_size = 2M read_buffer_size = 1M read_rnd_buffer_size = 1M */ -- ================================ -- 9. 定期维护脚本 -- ================================ -- 创建定期维护事件 DELIMITER // CREATE EVENT IF NOT EXISTS `ev_daily_maintenance` ON SCHEDULE EVERY 1 DAY STARTS CURRENT_TIMESTAMP DO BEGIN -- 更新过期VIP用户 UPDATE `user` SET vip_level = 0 WHERE vip_expire_at < NOW() AND vip_level > 0; -- 优化表 OPTIMIZE TABLE `user`; OPTIMIZE TABLE `movie`; OPTIMIZE TABLE `episode`; -- 分析表 ANALYZE TABLE `user`; ANALYZE TABLE `movie`; ANALYZE TABLE `episode`; -- 记录维护日志 INSERT INTO `system_log` (type, message, created_at) VALUES ('maintenance', 'Daily maintenance completed', NOW()); END // DELIMITER ; -- 启用事件调度器 SET GLOBAL event_scheduler = ON; -- ================================ -- 10. 备份建议 -- ================================ /* 数据库备份脚本示例: #!/bin/bash # 数据库备份脚本 DB_NAME="nl_video_db" DB_USER="root" DB_PASS="password" BACKUP_DIR="/backup/mysql" DATE=$(date +%Y%m%d_%H%M%S) # 创建备份目录 mkdir -p $BACKUP_DIR # 全量备份 mysqldump -u$DB_USER -p$DB_PASS --single-transaction --routines --triggers $DB_NAME > $BACKUP_DIR/full_backup_$DATE.sql # 压缩备份文件 gzip $BACKUP_DIR/full_backup_$DATE.sql # 删除7天前的备份 find $BACKUP_DIR -name "full_backup_*.sql.gz" -mtime +7 -delete echo "Backup completed: full_backup_$DATE.sql.gz" */ -- ================================ -- 执行完成提示 -- ================================ SELECT 'Database optimization completed successfully!' as message; SELECT 'Please restart MySQL service to apply configuration changes.' as note; SELECT 'Run SHOW PROCESSLIST; to monitor current queries.' as monitoring_tip;