0
点赞
收藏
分享

微信扫一扫

ASTM C1186-22 纤维水泥平板

捌柒陆壹 04-07 19:30 阅读 1

SQL 优化/慢查询

前言

索引优化和sql优化区别

索引优化

  • 索引优化侧重于优化数据库中的索引结构,以提高查询性能。
  • 它涉及选择合适的索引类型、确定哪些列应该创建索引、以及如何组织这些索引以最大程度地提高查询速度。
  • 索引优化的目标是通过减少数据检索的行数和提高数据检索速度来优化数据库的性能。

SQL 调优

  • SQL 调优是通过改进 SQL 查询语句的结构和执行计划来提高查询性能。
  • 它包括重构查询以减少资源消耗、使用更有效的连接方法、避免不必要的操作等。
  • SQL 调优的目标是优化查询的执行计划,使查询更有效率地访问数据,并减少查询执行所需的时间和资源。

SQL优化的情况

可以走索引

  • 应该走索引,但是没走
  • 走索引了,但是没到最优(explain 分析,type 一般我们要求至少到达 range 这个级别)
  • order by 和 group by 优化

没法走索引

  • 或者 type 是 index,而且数据量大
  • 了解适用索引的情况,请不要只有面试时会说,工作就不知道了(数据量不大,直接查没事;大的话,考虑引进其他技术解决,如 :Redis, MongoDB, elasticsearch等)

小表驱动大表

  • 假设我们有两个表,一个是小表 small_table,另一个是大表 large_table,它们之间通过某个字段进行关联,我们想要查询大表中满足某些条件的数据。
-- 创建一个小表
CREATE TABLE small_table (
    id INT PRIMARY KEY,
    name VARCHAR(50)
);

-- 创建一个大表
CREATE TABLE large_table (
    id INT PRIMARY KEY,
    small_table_id INT,
    some_data VARCHAR(100),
    FOREIGN KEY (small_table_id) REFERENCES small_table(id)
);

-- 示例数据插入
INSERT INTO small_table (id, name) VALUES (1, 'Small1'), (2, 'Small2');

INSERT INTO large_table (id, small_table_id, some_data) VALUES 
(101, 1, 'Data1 related to Small1'),
(102, 2, 'Data2 related to Small2'),
(103, 1, 'Data3 related to Small1');
  • 面是一个简单的查询,演示如何使用小表驱动大表:
SELECT lt.id, lt.some_data
FROM large_table lt
JOIN small_table st ON lt.small_table_id = st.id
WHERE st.name = 'Small1';

在这里插入图片描述

使用limit

  • 分页查询
-- 分页查询,每页返回10条数据
SELECT * FROM table_name LIMIT 10 OFFSET 0; -- 第一页
SELECT * FROM table_name LIMIT 10 OFFSET 10; -- 第二页
  • 快速验证数据
-- 获取前10条数据进行验证
SELECT * FROM table_name LIMIT 10;
  • 优先级排序
-- 获取最新的10个订单
SELECT * FROM orders ORDER BY order_date DESC LIMIT 10;
  • 限制联合查询结果
-- 获取每个用户的最新5条订单
SELECT * FROM (
    SELECT * FROM orders WHERE user_id = 1 ORDER BY order_date DESC LIMIT 5
) AS user_orders
UNION ALL
SELECT * FROM (
    SELECT * FROM orders WHERE user_id = 2 ORDER BY order_date DESC LIMIT 5
) AS user_orders;

将包含大量值的子查询改写为连接操作

  • IN 子查询的示例
-- 使用IN子查询
SELECT * 
FROM orders 
WHERE customer_id IN (SELECT id FROM customers WHERE last_name = 'Smith');
  • 连接操作来优化这个查询
-- 使用连接操作
SELECT o.* 
FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE c.last_name = 'Smith';

在这里插入图片描述

增量查询代替limit分页查询

  • 分页查询
-- 使用LIMIT进行分页查询
SELECT * FROM orders ORDER BY created_at LIMIT 10 OFFSET 0; -- 第一页
SELECT * FROM orders ORDER BY created_at LIMIT 10 OFFSET 10; -- 第二页
  • 增量查询
-- 使用增量查询获取分页数据
-- 假设上一页最后一行数据的 created_at 时间为 'last_timestamp'
SELECT * FROM orders WHERE created_at > 'last_timestamp' ORDER BY created_at LIMIT 10;

提升group by的效率

  • 先过滤数据,再分组
SELECT 
    customer_id,
    SUM(order_amount) AS total_amount
FROM 
    orders
WHERE 
    order_date BETWEEN '2024-01-01' AND '2024-01-31'
GROUP BY 
    customer_id;
  • 先分组,再过滤数据
SELECT 
    customer_id,
    SUM(order_amount) AS total_amount
FROM (
    SELECT 
        customer_id,
        order_amount
    FROM 
        orders
    GROUP BY 
        customer_id, order_amount
) AS subquery
WHERE 
    order_date BETWEEN '2024-01-01' AND '2024-01-31'
GROUP BY 
    customer_id;
方法执行步骤优点缺点
先过滤数据,再分组1. 过滤数据
2. 分组
1. 可以在过滤数据后处理更少的行,提高查询效率。
2. 可以更直观地表达查询意图,容易理解。
1. 如果分组前的数据量仍然很大,分组操作仍可能会消耗大量资源。
2. 对于某些查询条件,不一定能够有效地减少分组前的数据量。
先分组,再过滤数据1. 分组
2. 过滤数据
1. 可以更早地进行聚合操作,减少了过滤后的数据量。
2. 对于某些查询条件,可以更有效地减少分组前的数据量。
1. 如果分组后的数据量仍然很大,过滤操作可能仍会消耗大量资源。
2. 对于某些查询条件,可能会导致额外的分组操作,增加了查询的复杂度。

慢查询

慢查询的定义

什么情况慢查询

索引问题

在这里插入图片描述

索引优化

数据库结构设计

  • 假设我们有一个简单的订单管理系统,其中包含 orders 表和 order_items 表。orders 表存储订单信息,order_items 表存储订单中的商品条目信息。这两个表的结构如下:
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    customer_id INT,
    order_date DATE,
    -- 其他订单相关字段
);

CREATE TABLE order_items (
    order_item_id INT PRIMARY KEY,
    order_id INT,
    product_id INT,
    quantity INT,
    price DECIMAL(10,2),
    -- 其他订单商品相关字段
);
  • 现在,我们需要查询某个客户最近一段时间内的订单总金额。我们可以使用以下 SQL 查询:
SELECT 
    o.customer_id,
    SUM(oi.quantity * oi.price) AS total_amount
FROM 
    orders o
JOIN 
    order_items oi ON o.order_id = oi.order_id
WHERE 
    o.customer_id = 123
    AND o.order_date BETWEEN '2024-01-01' AND '2024-03-31'
GROUP BY 
    o.customer_id;

表结构优化

  • 创建合适的索引
    在这里插入图片描述
CREATE INDEX idx_orders_customer_date ON orders(customer_id, order_date);
CREATE INDEX idx_order_items_order_id ON order_items(order_id);

数据库参数配置问题

  • 查看数据库的当前的配置
-- 最大连接数
SHOW VARIABLES LIKE 'max_connections';
-- 缓冲区大小
SELECT * FROM sys.dm_os_sys_memory;
-- 日志文件大小
SELECT * FROM sys.master_files WHERE type_desc = 'LOG';
  • 优化最大连接数的参数sql
-- 设置最大连接数为1000
SET GLOBAL max_connections = 1000;
  • 调整缓冲区大小
-- 设置 InnoDB 缓冲池大小为 4GB
SET GLOBAL innodb_buffer_pool_size = 4G;
  • 调整日志文件大小sql
-- 修改 redo log 文件大小为 1GB
SET GLOBAL innodb_log_file_size = 1073741824;
  • 分区表
  • 数据库垂直拆分和水平
举报

相关推荐

0 条评论