首页 数据库 千万级的大表,如何做性能调优?

千万级的大表,如何做性能调优?

前言

大表优化是一个老生常谈的话题,但随着业务规模的增长,总有人会“中招”。

很多小伙伴的数据库在刚开始的时候表现良好,查询也很流畅,但一旦表中的数据量上了千万级,性能问题就开始浮现,查询慢、写入卡、分页拖沓、甚至偶尔直接宕机。这

时大家可能会想,是不是数据库不行?是不是需要升级到更强的硬件?

其实很多情况下,根本问题在于没做好优化

今天,我们就从问题本质讲起,逐步分析大表常见的性能瓶颈,以及如何一步步优化。

我最近开源了一个基于 SpringBoot+Vue+uniapp 的商城项目,里面的技术亮点挺多的,欢迎访问和star。[https://gitee.com/dvsusan/susan_mall]

一、为什么大表会慢?

在搞优化之前,先搞清楚大表性能问题的根本原因。数据量大了,为什么数据库就慢了?

1. 磁盘IO瓶颈

大表的数据是存储在磁盘上的,数据库的查询通常会涉及到数据块的读取。

当数据量很大时,单次查询可能需要从多个磁盘块中读取大量数据,磁盘的读写速度会直接限制查询性能。

举例:

假设有一张订单表orders,里面存了5000万条数据,你想要查询某个用户的最近10条订单:

SELECT * FROM orders WHERE user_id = 123 ORDER BY order_time DESC LIMIT 10;

如果没有索引,数据库会扫描整个表的所有数据,再进行排序,性能肯定会拉胯。

2. 索引失效或没有索引

如果表的查询没有命中索引,数据库会进行全表扫描(Full Table Scan),也就是把表里的所有数据逐行读一遍。

这种操作在千万级别的数据下非常消耗资源,性能会急剧下降。

举例:

比如你在查询时写了这样的条件:

SELECT * FROM orders WHERE DATE(order_time) = '2023-01-01';

这里用了DATE()函数,数据库需要对所有记录的order_time字段进行计算,导致索引失效。

3. 分页性能下降

分页查询是大表中很常见的场景,但深度分页(比如第100页之后)会导致性能问题。

即使你只需要10条数据,但数据库仍然需要先扫描出前面所有的记录。

举例:

查询第1000页的10条数据:

SELECT * FROM orders ORDER BY order_time DESC LIMIT 9990, 10;

这条SQL实际上是让数据库先取出前9990条数据,然后丢掉,再返回后面的10条。

随着页码的增加,查询的性能会越来越差。

4. 锁争用

在高并发场景下,多个线程同时对同一张表进行增删改查操作,会导致行锁或表锁的争用,进而影响性能。

二、性能优化的总体思路

性能优化的本质是减少不必要的IO、计算和锁竞争,目标是让数据库尽量少做“无用功”。

优化的总体思路可以总结为以下几点:

  1. 表结构设计要合理:尽量避免不必要的字段,数据能拆分则拆分。
  2. 索引要高效:设计合理的索引结构,避免索引失效。
  3. SQL要优化:查询条件精准,尽量减少全表扫描。
  4. 分库分表:通过水平拆分、垂直拆分减少单表数据量。
  5. 缓存和异步化:减少对数据库的直接压力。

接下来,我们逐一展开。

三、表结构设计优化

表结构是数据库性能优化的基础,设计不合理的表结构会导致后续的查询和存储性能问题。

1. 精简字段类型

字段的类型决定了存储的大小和查询的性能。

  • 能用INT的不要用BIGINT
  • 能用VARCHAR(100)的不要用TEXT
  • 时间字段建议用TIMESTAMPDATETIME,不要用CHARVARCHAR来存时间。

举例:

-- 不推荐CREATE TABLE orders (
    id BIGINT,
    user_id BIGINT,
    order_status VARCHAR(255),
    remarks TEXT
);-- 优化后CREATE TABLE orders (
    id BIGINT,
    user_id INT UNSIGNED,
    order_status TINYINT, -- 状态用枚举表示
    remarks VARCHAR(500) -- 限制最大长度
);

这样可以节省存储空间,查询时也更高效。

2. 表拆分:垂直拆分与水平拆分

垂直拆分

当表中字段过多,某些字段并不是经常查询的,可以将表按照业务逻辑拆分为多个小表。

示例
将订单表分为两个表:orders_basic 和 orders_details

-- 基本信息表CREATE TABLE orders_basic (
    id BIGINT PRIMARY KEY,
    user_id INT UNSIGNED,
    order_time TIMESTAMP
);-- 详情表CREATE TABLE orders_details (
    id BIGINT PRIMARY KEY,
    remarks VARCHAR(500),
    shipping_address VARCHAR(255)
);

水平拆分

当单表的数据量过大时,可以按一定规则拆分到多张表中。

示例
假设我们按用户ID对订单表进行水平拆分:

orders_0 -- 存user_id % 2 = 0的订单
orders_1 -- 存user_id % 2 = 1的订单

拆分后每张表的数据量大幅减少,查询性能会显著提升。

四、索引优化

索引是数据库性能优化的“第一杀器”,但很多人对索引的使用并不熟悉,导致性能不升反降。

1. 创建合适的索引

为高频查询的字段创建索引,比如主键、外键、查询条件字段。

示例:

CREATE INDEX idx_user_id_order_time ON orders (user_id, order_time DESC);

上面的复合索引可以同时加速user_idorder_time的查询。

2. 避免索引失效

  • 别对索引字段使用函数或运算
    错误:

    SELECT * FROM orders WHERE DATE(order_time) = '2023-01-01';

    优化:

    SELECT * FROM orders WHERE order_time >= '2023-01-01 00:00:00'  AND order_time < '2023-01-02 00:00:00';
  • 注意隐式类型转换
    错误:

    SELECT * FROM orders WHERE user_id = '123';

    优化:

    SELECT * FROM orders WHERE user_id = 123;

五、SQL优化

1. 减少查询字段

只查询需要的字段,避免SELECT *

-- 错误SELECT * FROM orders WHERE user_id = 123;-- 优化SELECT id, order_time FROM orders WHERE user_id = 123;

2. 分页优化

深度分页时,使用“延迟游标”的方式避免扫描过多数据。

-- 深分页(性能较差)SELECT * FROM orders ORDER BY order_time DESC LIMIT 9990, 10;-- 优化:使用游标

SELECT * FROM orders WHERE order_time < '2023-01-01 12:00:00'  ORDER BY order_time DESC LIMIT 10;

六、分库分表

1. 水平分库分表

当单表拆分后仍无法满足性能需求,可以通过分库分表将数据分散到多个数据库中。

常见的分库分表规则:

  • 按用户ID取模。
  • 按时间分区。

七、缓存与异步化

1. 使用Redis缓存热点数据

对高频查询的数据可以存储到Redis中,减少对数据库的直接访问。

示例:

// 从缓存读取数据String result = redis.get("orders:user:123");if (result == null) {
    result = database.query("SELECT * FROM orders WHERE user_id = 123");
    redis.set("orders:user:123", result, 3600); // 设置缓存1小时
}

2. 使用消息队列异步处理写操作

高并发写入时,可以将写操作放入消息队列(如Kafka),然后异步批量写入数据库,减轻数据库压力。

八、实战案例

问题:

某电商系统的订单表存储了5000万条记录,用户查询订单详情时,页面加载时间超过10秒。

解决方案:

  1. 垂直拆分订单表:将订单详情字段拆分到另一个表中。
  2. 创建复合索引:为user_idorder_time创建索引。
  3. 使用Redis缓存:将最近30天的订单缓存到Redis中。
  4. 分页优化:使用search_after代替LIMIT深分页。

九、总结

大表性能优化是一个系统性工程,需要从表结构、索引、SQL到架构设计全方位考虑。

千万级别的数据量看似庞大,但通过合理的拆分、索引设计和缓存策略,可以让数据库轻松应对。

最重要的是,根据业务特点选择合适的优化策略,切勿盲目追求“高大上”的方案

希望这些经验能帮到你!

最后说一句(求关注,别白嫖我)

如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下我的同名公众号:苏三说技术,您的支持是我坚持写作最大的动力。

求一键三连:点赞、转发、在看。

关注公众号:【苏三说技术】,在公众号中回复:进大厂,可以免费获取我最近整理的10万字的面试宝典,好多小伙伴靠这个宝典拿到了多家大厂的offer。

站心网

前言大表优化是一个老生常谈的话题,但随着业务规模的增长,总有人会“中招”。很多小伙伴的数据库在刚开始..

为您推荐

GreenSock: 高性能的 HTML5 动画库

在现代网页开发中,动画已经成为提升用户体验的关键元素。无论是滚动效果、页面切换、按钮点击还是复杂的交互动画,良好的动画效果不仅能吸引用户,还能使界面更加生动、易用。GreenSock(GSAP,GreenSock Animation..

Elasticsearch性能优化干货

1、集群规划优化实践1.1 基于目标数据量规划集群在业务初期,经常被问到的问题,要几个节点的集群,内存、CPU要多大,要不要SSD?最主要的考虑点是:你的目标存储数据量是多大?可以针对目标数据量反推节点多少。1.2..

5个高性能 .NET Core 图片处理库推荐

在使用 .NET Core 开发中,图片处理是一个常见需求,如图像缩放、裁剪、格式转换和添加水印等。以下是一些推荐的 .NET Core 图片处理库,它们功能强大且支持多种图像处理功能:1. ImageSharp简介:ImageSharp 是一个..

如何优化ASP.NET Core应用的性能?

优化ASP.NET Core应用性能需要从代码、数据库、配置、服务器和部署等多个层面进行综合考虑。以下是一些优化ASP.NET Core应用性能的关键方法和技巧:1. 代码级优化使用异步编程:避免阻塞线程,通过async和await处理I..

SQLite性能支持多少数据量?

SQLite是一种轻量级的关系型数据库管理系统,广泛应用于移动应用、嵌入式系统和小型桌面应用程序中。由于其零配置、自给自足的特性,SQLite在很多场景下非常受欢迎。然而,对于许多开发者来说,一个常见的问题是:SQ..

Sylvan.Data.Excel 性能优异的开源.NET Excel数据读取库

Sylvan.Data.Excel是一个开源、免费、跨平台的.NET库,专注于读取和写入Excel数据文件。支持多种文件格式,并提供高效的数据访问和数据绑定功能。该库在.NET生态系统中是读取Excel数据文件的最快且内存分配最低的库..

SQL Server用UUID做主键性能问题和解决方案

在 SQL Server 中使用 UUID(全称:Universally Unique Identifier) 作为主键确实可能带来一些性能问题,特别是在大型数据库和高写入负载的场景下。以下是一些关键的性能挑战及其原因:1. 无序插入导致索引碎片化UU..

.NET Core记录请求处理时间的中间件

以下是一个示例的 .NET Core 中间件,用于记录请求处理时间的情况:using Microsoft.AspNetCore.Http;using Microsoft.Extensions.Logging;using System;using System.Diagnostics;using System.Threading.Tasks;pub..

VS2022性能分析工具如何使用?

Visual Studio 2022提供了强大的性能分析工具,可以帮助开发人员识别和解决应用程序的性能问题。下面是使用VS2022性能分析工具的一般步骤:打开Visual Studio 2022,并打开要分析的项目。在菜单栏中选择"调试",然后..

.NET高性能大并发解决方案

.NET 提供了多种技术来提高应用程序的性能和并发能力。以下是一些常见的解决方案:使用任务并行库(TPL):TPL 提供了一种简单的方法来并行执行多个任务,从而提高性能。在 .NET Core 中,可以使用 Task 类来创建和..

c# 遍历list哪个方式性能最高

在 C# 中遍历 List 的性能可以通过以下几种方式进行比较:使用 for 循环:for (int i = 0; i < list.Count; i++){var item = list[i];// 进行操作}使用 foreach 循环:foreach (var item in list){// 进行操作}使用 ..

VS2017自带的性能分析工具使用方法

本文简单的介绍如何使用VS2017自带的性能分析工具。.NET性能分析工具,比较有名的是JetBrains.dotTrace,但是他只免费十天啊,其实VS就自带了性能分析工具,我们天天用VS写代码,有没有注意过它自带的性能分析功能呢..

.NET性能分析工具MiniProfiler使用示例

MiniProfiler是一个用于应用程序性能分析的轻量级工具,最初由Stack Exchange团队创建。Stack Exchange是知名的问答网站(如Stack Overflow)的背后团队,他们开发了许多开源工具和库来支持他们的产品和开发流程。Mi..

.NET网站性能优化方案

.NET 网站的性能优化是一个综合性的过程,涉及多个方面,包括前端和后端优化、服务器配置、代码优化等。下面是一些.NET网站性能优化的方案:1. 前端优化:减少 HTTP 请求:合并、压缩和缓存静态资源(CSS、JavaScrip..

.NET架构师技术要求:掌握.NET平台和架构设计能力

作为一个.NET架构师,你需要具备以下技术要求:精通.NET平台:作为.NET架构师,你应该对.NET平台和相关技术栈有深入的理解,包括.NET Framework和.NET Core。你应该熟悉.NET编程语言,如C#,以及相关的.NET开发工具..

如何进行.NET应用程序的性能优化?请谈谈你在性能优化方面的经验和使用的技术

.NET应用程序的性能优化是确保应用程序在响应时间、吞吐量和资源利用方面具有良好性能的关键任务。以下是一些我在性能优化方面的经验和使用的技术:代码优化:优化代码可以改善应用程序的性能。这包括避免不必要的循..

Visual Studio vs2022性能分析工具性能探查器使用方法

Visual Studio 2022 提供了多种性能分析工具,可用于分析和优化代码性能。下面是一些常见的性能分析工具及其使用方法:CPU 使用率该工具可用于监测 CPU 使用情况,并可在 Visual Studio 中查看每个函数和代码段的 CP..

.NET网站性能分析工具

在.NET生态系统中,有许多性能分析工具可用于评估和优化网站的性能。以下是一些常用的.NET网站性能分析工具:dotMemory类型:内存分析工具描述:dotMemory是JetBrains提供的一款强大的.NET内存分析工具,可用于检测..

C#的网站通过Windows性能计数器监测服务器的性能

背景使用C#开发的网站,很想知道服务器运行时,相关的各种性能参数。比如:CPU利用率,磁盘读写速度,网络带宽占用,网站链接数等等。如果能够有图表的方式显示就更好了。如果服务器是Windows操作系统,可以通过Wind..

.NET部署到Linux和Windows哪个性能更高?

C#可以使用.NET Core在Linux上运行。.NET Core是一个开源的、跨平台的.NET框架,支持Linux、Windows和macOS。要在Linux上运行C#,您需要安装.NET Core SDK。那么.NET部署到Linux和Windows哪个性能更高呢?一般来说,..

发表回复

返回顶部