mysql

25 阅读6分钟
mysql 慢查询该如何优化
  • 定位慢查询
    • 开启慢查询日志开关,设置慢查询阈值,比如1秒
    • 内置工具,统计慢查询的执行频率、耗时等 & 第三方工具
  • 优化SQL语句
    • 检查是否全表扫描,select *
    • 优化JOIN:确保关联字段有索引,join表过多,小表驱动大表
    大表:employees:e_id,name,department_id
    小表:departments:d_id,department_name
    
    select e.name ,d.department_name  
    from departments d  
    JOIN employess e 
    ON d.id = e.department_id;
    
    • 减少子查询,子查询可能导致临时表创建
    • 优化排序/分组,order by/groupby的字段尽量使用索引
  • 优化索引
    • 创建复合索引,将过滤性强的字段放前面
    • 删除冗余字段
    • 创建合适的索引,在where,join \order by后的字段建立索引
  • 优化数据表结构
    • 分库分表
      • 水平分表:将大表按照时间,用户ID拆分成小表
      • 垂直分表:将不常用的大字段(text)拆分到单独表,减少主表数据量
  • 优化数据库配置
    • 调整合适的最大连接数,避免连接耗尽
    • 优化缓存:增大innodb_buffer_pool_size(建议设为物理内存的 50%-70%),减少磁盘 IO
    • 调整 IO 相关参数innodb_flush_log_at_trx_commit设为 1 保证 ACID,或提升性能(牺牲部分安全性)
  • 应用层优化:添加缓存(如 Redis)减少数据库访问,批量操作代替循环单条操作。
SQL的执行顺序

SQL查询通常按照以下顺序执行:

FROM 子句:选定数据来源的表。
WHERE 子句:筛选出满足条件的行。
GROUP BY 子句:对数据进行分组。
HAVING 子句:筛选分组后满足条件的组。
SELECT 子句:选择最终展示的列。
ORDER BY 子句:对结果进行排序。
LIMIT 子句:限制返回的行数。

找出那些高薪员工(工资>65000)的平均工资超过75,000的部门,并按平均工资从高到低排序

employee_id | department | salary |                                        |
| ----------- | ---------- | ------ | -------------------------------------- |
| 1           | IT         | 80000  |                                        |
| 2           | IT         | 70000  | // IT平均薪水 = (80k + 70k)/2 = **75k**    |
| 3           | Sales      | 90000  |                                        |
| 4           | Sales      | 80000  | // Sales平均薪水 = (90k + 80k)/2 = **85k** |
| 5           | HR         | 70000  | // 被 Having 过滤掉(平均薪水<=65k)                |
| 6           | HR         | 50000  | // 被 WHERE 过滤掉(薪水<=65k)                |

select department,AVG(salary) as avg_salary

from employess

where salary > 65000

group by department

having by avg_salary > 75000

order by avg_salary desc;
**最终结果:**

| department | avgsalary |
| ---------- | --------- |
| Sales      | 85000     |

如果没有`HAVING`子句,结果将会是:

| department | avgsalary |                    |
| ---------- | --------- | ------------------ |
| Sales      | 85000     |                    |
| IT         | 75000     | // 这行也会出现,但你可能不想要它
事务的四大特性(ACID)

数据库事务:数据库事务用于确保一组操作为一个原子单元被执行,要么全部成功,要么全部失败,保证数据的一致性。

  • 原子性
  • 隔离性
  • 一致性
  • 持久性
视图
  • 作用
    视图是一个虚拟表,它根据查询结果集动态生成,可以用于简化复杂查询、提高安全性和维护性
  • 解释
    视图并不存储数据,而是提供一种从一个或多个表中查询数据的方式。视图可以定义时计算复杂的查询,之后像普通表一样使用。
CREATE VIEW it_employees AS 
SELECT name, salary 
FROM employees 
WHERE department = 'IT';

select * from it_employees;

结果将返回所有IT部门员工的姓名和工资。这种方式简化了查询和限制了对原始表的直接访问。

MySQL中的外键
  • 作用
    外键用于建立和维护两个表之间的参照完整性,确保数据的一致性和准确性。

  • 解释
    外键约束定义了一列或多列在一个表中必须与另一个表中的主键或唯一键相匹配,确保数据的对应关系。

CREATE TABLE customers (
  customer_id INT PRIMARY KEY,
  name VARCHAR(255)
);

CREATE TABLE orders (
  order_id INT PRIMARY KEY,
  customer_id INT,
  amount DECIMAL(10, 2),
  FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);

orders表的customer_id是外键,它保证了每个订单都属于有效的客户。如果尝试插入一个不存在的customer_id,数据库将返回错误,从而保护数据的一致性。

如何保证在高并发情况下安全地修改同一行数据

可以使用锁机制,如行级锁、乐观锁和悲观锁。

  1. 行级锁:只锁定被修改的行,使其他操作可以继续。
  2. 乐观锁:基于版本号或时间戳,检测数据是否被修改,进行冲突检测。
  3. 悲观锁:在操作前获取锁,直到操作完成,避免其他事务访问。
UPDATE accounts 
SET balance = balance - 100, version = version + 1 
WHERE account_id = 'A' AND version = 1;

应用程序需在读取数据时带上最新版本号,通过版本号判断数据是否已被其他事务修改。

MySQL中如何处理和优化重复数据

可以使用多种方法检测和优化重复数据:

  • 使用DISTINCT关键字查询去重的结果。
  • 利用GROUP BY及聚合函数统计重复的行。
  • 创建唯一约束(UNIQUE)防止后续插入重复数据。
SQL优化的一般步骤是什么,怎么看执行计划(EXPLAIN)?
  • 1 识别慢查询: 使用 slow_query_log
  • 2 添加适当索引: 针对查询条件添加索引。
  • 3 重写查询: 尝试不同的查询方式或使用表连接。
  • 4 利用EXPLAIN: 理解 SQL 查询的执行过程。
SELECT * FROM employees WHERE department_id = 5;
使用 `EXPLAIN`:会显示使用的索引、扫描的行数等信息,帮助识别查询瓶颈。
EXPLAIN SELECT * FROM employees WHERE department_id = 5;

MySQL如何执行子查询,以及它们的性能影响是什么?
  • 子查询用于从一个查询的结果中作为另一个查询的输入,能提供灵活的数据检索.子查询可以写在SELECT, FROM, WHERE等子句中
  • 性能方面,子查询通常比JOIN更慢,因为每个子查询可能都是一个独立的SELECT语句,有时MySQL会执行多次。
MySQL的B树索引和哈希索引有什么区别?
  • B树索引:支持范围查询,适合于多种查询条件,维护过程中比较平衡,查询性能优异。
  • 哈希索引:只支持等值查询,检索速度快,但在范围查询时表现不佳。哈希索引最好用于查找单一值。