数据迁移脚本优化过程:从 MySQL 到 Django 模型表

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用版 2核4GB 50GB
简介: 在大规模的数据迁移过程中,性能问题往往是开发者面临的主要挑战之一。本文将分析一个数据迁移脚本的优化过程,展示如何从 MySQL 数据库迁移数据到 Django 模型表,并探讨优化前后的性能差异。

在大规模的数据迁移过程中,性能问题往往是开发者面临的主要挑战之一。本文将分析一个数据迁移脚本的优化过程,展示如何从 MySQL 数据库迁移数据到 Django 模型表,并探讨优化前后的性能差异。

优化前的脚本分析

优化前的脚本按批次从 MySQL 数据库中读取数据,并将其插入到 Django 模型表中。每次读取的数据量由 batch_size 确定。以下是优化前的关键部分:

fetch_sql = f"""
    SELECT search_rank, search_term,  `period`, report_date 
    FROM hot_search_terms_table 
    WHERE period = '{period}' 
    LIMIT %s OFFSET %s;
"""

每次查询使用 LIMITOFFSET 子句,OFFSET 指定从哪一行开始读取。然而,随着数据量的增加,OFFSET 会导致性能显著下降,因为数据库必须扫描更多行来确定结果集的起点。

优化后的脚本分析

优化后的脚本通过使用递增的主键 ID 进行分页查询,避免了 OFFSET 带来的性能问题。以下是优化后的关键部分:

fetch_sql = f"""
    SELECT id, search_rank, search_term,`period`, report_date 
    FROM hot_search_terms_table 
    WHERE period = %s AND id > %s 
    ORDER BY id ASC 
    LIMIT %s;
"""

通过 WHERE id > %sORDER BY id ASC,我们可以确保每次查询的结果集都是按主键 ID 排序的,性能大大提高,因为数据库可以直接从上一次查询结束的地方开始读取数据。

优化前后的性能比较

优化前的性能问题

  1. 查询性能下降:随着 OFFSET 值的增加,查询性能会显著下降。数据库需要扫描所有的行,直到达到指定的偏移量,然后返回后续的行。
  2. 长时间等待:当数据量较大时,随着偏移量的增加,每次查询所需的时间会变得越来越长。

优化后的性能改进

  1. 高效的分页查询:使用递增的主键 ID 进行分页查询,避免了扫描大量无关行的数据。
  2. 稳定的查询时间:每次查询都只需读取新的数据,无需扫描之前已经处理过的数据行,查询时间稳定且较快。

实施细节

优化前的实现

优化前的实现通过读取偏移量文件来记录上次处理的位置,每次查询都从该位置开始,读取一批数据并插入到 Django 模型表中:

class Command(BaseCommand):
    # 省略部分代码...

    def handle(self, *args, **kwargs):
        try:
            # 连接数据库
            mysql_conn = mysql.connector.connect(**mysql_config)
            mysql_cursor = mysql_conn.cursor()
            # 批次处理
            while True:
                self.stdout.write(self.style.SUCCESS(f"正在获取 {offset} -  {offset + batch_size} 行的数据"))
                zhilin_cursor.execute(fetch_sql, (batch_size, offset))
                batch_data = zhilin_cursor.fetchall()
                if not batch_data:
                    break

                # 转换并插入数据
                objects = [HotSearchTermsReportABA(...) for row in batch_data]
                with transaction.atomic():
                    HotSearchTermsReportABA.objects.bulk_create(objects)
                    offset += batch_size
                    total_rows_transferred += len(batch_data)
                    self.update_last_offset(offset)

        except Error as e:
            # 错误处理
            self.stdout.write(self.style.ERROR(f"传输过程中出现异常:{e}"))

优化后的实现

优化后的实现使用主键 ID 进行分页查询,并记录上次处理的最大 ID:

class Command(BaseCommand):
    # 省略部分代码...

    def handle(self, *args, **kwargs):
        try:
            # 连接数据库
            mysql_conn = mysql.connector.connect(**mysql_config)
            mysql_cursor = mysql_conn.cursor()
            # 批次处理
            while True:
                self.stdout.write(self.style.SUCCESS(f"正在获取 ID 大于 {last_id}{self.batch_size} 行数据"))
                zhilin_cursor.execute(fetch_sql, (period, last_id, self.batch_size))
                batch_data = zhilin_cursor.fetchall()
                if not batch_data:
                    break

                # 转换并插入数据
                objects = [HotSearchTermsReportABA(...) for row in batch_data]
                with transaction.atomic():
                    HotSearchTermsReportABA.objects.bulk_create(objects)
                    last_id = batch_data[-1][0]
                    total_rows_transferred += len(batch_data)
                    self.update_last_id(last_id)

        except Error as e:
            # 错误处理
            self.stdout.write(self.style.ERROR(f"传输过程中出现异常:{e}"))

总结

通过上述优化过程解决了数据量增大导致的查询性能下降问题。具体优化策略包括:

  1. 使用主键 ID 进行分页查询,避免 OFFSET 带来的性能问题。
  2. 确保每次查询只读取新的数据,减少数据库扫描的行数。
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
12天前
|
搜索推荐 前端开发 数据可视化
基于Python协同过滤的旅游景点推荐系统,采用Django框架,MySQL数据存储,Bootstrap前端,echarts可视化实现
本文介绍了一个基于Python协同过滤算法的旅游景点推荐系统,该系统采用Django框架、MySQL数据库、Bootstrap前端和echarts数据可视化技术,旨在为用户提供个性化的旅游推荐服务,提升用户体验和旅游市场增长。
基于Python协同过滤的旅游景点推荐系统,采用Django框架,MySQL数据存储,Bootstrap前端,echarts可视化实现
|
12天前
|
搜索推荐 前端开发 算法
基于用户画像及协同过滤算法的音乐推荐系统,采用Django框架、bootstrap前端,MySQL数据库
本文介绍了一个基于用户画像和协同过滤算法的音乐推荐系统,使用Django框架、Bootstrap前端和MySQL数据库构建,旨在为用户提供个性化的音乐推荐服务,提高推荐准确性和用户满意度。
基于用户画像及协同过滤算法的音乐推荐系统,采用Django框架、bootstrap前端,MySQL数据库
|
13天前
|
存储 关系型数据库 MySQL
基于python django 医院管理系统,多用户功能,包括管理员、用户、医生,数据库MySQL
本文介绍了一个基于Python Django框架开发的医院管理系统,该系统设计了管理员、用户和医生三个角色,具备多用户功能,并使用MySQL数据库进行数据存储和管理。
基于python django 医院管理系统,多用户功能,包括管理员、用户、医生,数据库MySQL
|
4天前
|
安全 关系型数据库 MySQL
分享一个 MySQL 简单快速进行自动备份和还原的脚本和方法
分享一个 MySQL 简单快速进行自动备份和还原的脚本和方法
|
8天前
|
SQL 存储 Oracle
MySQL 项目中 SQL 脚本更新、升级方式,防止多次重复执行
MySQL 项目中 SQL 脚本更新、升级方式,防止多次重复执行
18 0
|
29天前
|
存储 SQL 关系型数据库
MySQL设计规约问题之在数据库设计中,为什么要适当考虑反范式的表设计
MySQL设计规约问题之在数据库设计中,为什么要适当考虑反范式的表设计
|
29天前
|
SQL 存储 数据库
MySQL设计规约问题之如何处理日志类型的表
MySQL设计规约问题之如何处理日志类型的表
|
2月前
|
关系型数据库 MySQL 数据库
『Django』模型入门教程-操作MySQL
一个后台如果没有数据库可以说废了一半。日常开发中大多数时候都在与数据库打交道。Django 为我们提供了一种更简单的操作数据库的方式。 在 Django 中,模型(Model)是用来定义数据库结构的类。每个模型类通常对应数据库中的一个表,类的属性对应表中的列。通过定义模型,Django 的 ORM(Object-Relational Mapping)可以将 Python 对象映射到数据库表,并提供一套 API 来进行数据库操作。 本文介绍模型的用法。
|
1月前
|
运维 关系型数据库 MySQL
实时计算 Flink版产品使用问题之在处理MySQL表新增数据记录时,没有正确触发变更事件,该如何解决
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。

热门文章

最新文章