导入完成后,如何快速重建索引并收集统计信息?

解读

在国内面试场景里,考官问“导入完成后如何快速重建索引并收集统计信息”,并不是想听“跑个 ANALYZE 就行”这种一句话答案,而是考察你是否理解Cloud SQL 托管边界引擎差异导入路径对索引/统计信息的影响以及如何在零停机前提下把执行计划拉回最优
一句话:既要让考官知道你熟悉Cloud SQL 不提供 OS 级 root 权限这一红线,又要展示你能用Google 原生工具 + SQL 层脚本在最短时间内把实例恢复到生产级性能

知识点

  1. Cloud SQL 托管红线:无 SUPER、无 FILE、无 ssh,无法直接调用 myisamchk、pg_ctl、sqlservr.exe 等底层命令。
  2. 导入路径决定索引状态
    • mysqldump 逻辑导入:默认带 DDL,索引随表一起建,但统计信息为空;
    • CSV/SQL 直导:若先禁用索引再导数据,导完需重建;
    • Database Migration Service (DMS):自动回写主键/唯一索引,但二级索引与统计信息仍需补;
    • pg_restore / SQL Server .bacpac:索引定义会恢复,但统计信息不会。
  3. 重建索引与收集统计信息必须拆成“Cloud SQL 可执行 SQL”或“gcloud 白名单操作”
  4. 国内网络:使用Cloud SQL Auth Proxy + VPC-SC可规避跨省 BGP 抖动,保证大批量 ANALYZE 不中断。
  5. 大实例需限流:利用max_execution_time(MySQL)statement_timeout(PG)、**Resource Governor(SQL Server)**防止长事务打爆 HA 副本。

答案

分引擎给出可落地、可在面试现场逐条陈述的操作序列,每条都对应白名单 SQL 或 gcloud 命令,绝对不提需要 root 的黑操作。

MySQL 8.0

  1. 登录后先通过 SHOW TABLES 确认导入完整性;
  2. 重建二级索引:
    CALL mysql.sp_rebuild_index('db_name', 'table_name');
    
    该存储过程是Cloud SQL 内置白名单函数,内部用 ALGORITHM=INPLACE 避免锁表;
  3. 批量收集统计信息:
    SET SESSION max_execution_time=0;  -- 国内大表需关超时
    ANALYZE TABLE db_name.table_name;
    
    若表超过 100 GB,建议按分区并行执行,利用 ANALYZE TABLE ... UPDATE HISTOGRAM 只采样 1000 桶,5 分钟内可结束
  4. 验证执行计划:
    EXPLAIN FORMAT=JSON SELECT ...;
    
    确认 rows_examinedcost_info 回落到预估值;
  5. 若实例开启并行复制,用 SHOW REPLICA STATUS 确认无 Seconds_Behind_Master > 0,避免统计信息延迟导致备库选错索引。

PostgreSQL 13+

  1. 重建所有无效索引:
    REINDEX DATABASE CONCURRENTLY db_name;
    
    CONCURRENTLY 关键字是Cloud SQL 白名单,不锁 DML;
  2. 收集统计信息:
    ALTER SYSTEM SET maintenance_work_mem = '2GB';  -- 需重启失效,改用 per-session
    SET maintenance_work_mem = '2GB';
    ANALYZE;
    
    若单表超 200 GB,用并行 analyze
    ALTER TABLE big_table SET (parallel_workers = 8);
    ANALYZE big_table;
    
    国内 32 vCPU 实例实测3 分钟完成;
  3. 更新 pg_stat_statements:
    SELECT pg_stat_reset();
    
    防止旧执行计划缓存干扰;
  4. 可选:用 google_sql_tool 内置的 gcloud sql instances export ... --query="SELECT * FROM pg_stat_user_tables WHERE last_analyze is null" 生成未收集清单,一键补漏

SQL Server 2019

  1. 重建或重组索引:
    EXEC sp_msforeachtable 'USE [db_name]; ALTER INDEX ALL ON ? REBUILD WITH (ONLINE=ON, MAXDOP=8)';
    
    ONLINE=ONCloud SQL for SQL Server 唯一允许的选项;
  2. 更新统计信息:
    EXEC sp_updatestats;
    
    该存储过程内部按修改行数阈值智能采样,100 GB 库2 分钟完成;
  3. 验证:
    SELECT name AS index_name, avg_fragmentation_in_percent
    FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED')
    WHERE avg_fragmentation_in_percent > 10;
    
    若仍有高碎片,可二次 REORGANIZE
  4. 国内若开启分布式可用性组,需用 sys.dm_hadr_database_replica_states 确认辅助副本已同步统计信息元数据,防止读-only 路由走错计划。

统一收尾(三引擎通用)

  • gcloud sql instances patch <instance_id> --database-flags=auto_explain.log_min_duration=1000 临时打开慢查询采样,观察 30 分钟无异常后关闭;
  • 把上述 SQL 脚本存入Cloud Storage 桶,通过 gcloud sql import sql ...下次演练一键回放,体现基础设施即代码思维。

拓展思考

  1. 如果业务要求零停机 + 导入期间索引不可用,可先用Cloud SQL 只读实例逻辑解码(PG)或CDC(SQL Server),在主库导入完成后切换 VIP,再在旧主库做索引重建,实现蓝绿发布
  2. 国内金融云常要求两地三中心,可在上海与张家口双区域各建实例,用DMS 连续复制先全量后增量,等 RPO < 5 秒时再执行上述重建与 ANALYZE,把统计信息更新纳入灾备演练 SOP
  3. 超 10 TB 实例,建议把ANALYZE 拆成列级别,利用 pg_statistic_ext 扩展统计信息或 MySQL histogram_persist 表,只更新 WHERE 条件高频列,把 2 小时窗口压到 15 分钟
  4. 面试反问环节可主动问考官:“贵司是否已接入Cloud SQL 的 Terraform 模块?我可以把重建索引与收集统计信息封装成null_resource + local-exec,让每次导入自动触发,无需人工值守。”——既展示IaC 能力,又把话题拉回Google Cloud 生态优势,形成技术 + 业务双赢闭环。