如何优化MYSQL性能

48次阅读
没有评论

共计 7098 个字符,预计需要花费 18 分钟才能阅读完成。

本篇文章给大家分享的是有关如何优化 MYSQL 性能,丸趣 TV 小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着丸趣 TV 小编一起来看看吧。

1. MySQL 性能优化简介

在 Web 应用程序体系架构中,数据持久层 (通常是一个关系数据库) 是关键的核心部分,它对系统的性能有非常重要的影响。MySQL 是目前使用最多的开源数据库,但是 MySQL 数据库的默认设置性能非常的差,仅仅是一个玩具数据库。因此在产品中使用 MySQL 数据库必须进行必要的优化。

优化是一个复杂的任务,本文描述 MySQL 相关的数据库设计和查询优化,服务器端优化,存储引擎优化。

2. 数据库设计和查询优化

在 MySQL 性能优化中,首先要考虑的就是 Database Schema 设计,这一点是非常重要的。一个糟糕的 Schema 设计即使在性能调优的 MySQL Server 上运行,也会表现出很差的性能; 和 Schema 相似,查询语句的设计也会影响 MySQL 的性能,应该避免写出低效的 SQL 查询。这一节将详细讨论这两方面的优化。

2.1 Schema Design

Schema 的优化取决于将要运行什么样的 query,不同的 query 会有不同的 Schema 优化方案。2.2 节将介绍 Query Design 的优化。Schema 设计同样受到预期数据集大小的影响。Schema 设计时主要考虑:标准化,数据类型,索引。

2.1.1 标准化

标准化是在数据库中组织数据的过程。其中包括,根据设计规则创建表并在这些表间建立关系; 通过取消冗余度与不一致相关性,该设计规则可以同时保护数据并提高数据的灵活性。通常数据库标准化是让数据库设计符合某一级别的范式,通常满足第三范式即可。也有第四范式 (也称为 Boyce Codd 范式,BCNF)) 与第五范式存在,但是在实际设计中很少考虑。忽视这些规则可能使得数据库的设计不太完美,但这不应影响功能。

标准化的特点:

1) 所有的“对象”都在它自己的 table 中,没有冗余。

2) 数据库通常由 E - R 图生成。

3) 简洁,更新属性通常只需要更新很少的记录。

4) Join 操作比较耗时。

5) Select,sort 优化措施比较少。

6) 适用于 OLTP 应用。

非标准化的特点:

1) 在一张表中存储很多数据,数据冗余。

2) 更新数据开销很大,更新一个属性可能会更新很多表,很多记录。

3) 在删除数据是有可能丢失数据。

4) Select,order 有很多优化的选择。

5) 适用于 DSS 应用。

标准化和非标准化都有各自的优缺点,通常在一个数据库设计中可以混合使用,一部分表格标准化,一部分表格保留一些冗余数据:

1) 对 OLTP 使用标准化,对 DSS 使用非标准化

2) 使用物化视图。MySQL 不直接支持该数据库特性,但是可以用 MyISAM 表代替。

3) 冗余一些数据在表格中,例如将 ref_id 和 name 存在同一张表中。但是要注意更新问题。

4) 对于一些简单的对象,直接使用 value 作为建。例如 IP address 等

5) Reference by PRIMARY/UNIQUE KEY。MySQL 可以优化这种操作,例如:

java 代码

select city_name from city,state where state_id=state.id and state.code=‘CA’”converted to“select city_name from city where state_id=12

2.1.2 数据类型

最基本的优化之一就是使表在磁盘上占据的空间尽可能小。这能带来性能非常大的提升,因为数据小,磁盘读入较快,并且在查询过程中表内容被处理所占用的内存更少。同时,在更小的列上建索引,索引也会占用更少的资源。

可以使用下面的技术可以使表的性能更好并且使存储空间最小:

1) 使用正确合适的类型,不要将数字存储为字符串。

2) 尽可能地使用最有效 (最小) 的数据类型。MySQL 有很多节省磁盘空间和内存的专业化类型。

3) 尽可能使用较小的整数类型使表更小。例如,MEDIUMINT 经常比 INT 好一些,因为 MEDIUMINT 列使用的空间要少 25%。

4) 如果可能,声明列为 NOT NULL。它使任何事情更快而且每列可以节省一位。注意如果在应用程序中确实需要 NULL,应该毫无疑问使用它,只是避免 默认地在所有列上有它。

5) 对于 MyISAM 表,如果没有任何变长列(VARCHAR、TEXT 或 BLOB 列),使用固定尺寸的记录格式。这比较快但是不幸地可能会浪费一些空间。即使你已经用 CREATE 选项让 VARCHAR 列 ROW_FORMAT=fixed,也可以提示想使用固定长度的行。

6) 使用 sample character set,例如 latin1。尽量少使用 utf-8,因为 utf- 8 占用的空间是 latin1 的 3 倍。可以在不需要使用 utf- 8 的字段上面使用 latin1,例如 mail,url 等。

2.1.3 索引

所有 MySQL 列类型可以被索引。对相关列使用索引是提高 SELECT 操作性能的最佳途径。使用索引应该注意以下几点:

1) MySQL 只会使用前缀,例如 key(a, b) …where b=5 将使用不到索引。

2) 要选择性的使用索引。在变化很少的列上使用索引并不是很好,例如性别列。

3) 在 Unique 列上定义 Unique index。

4) 避免建立使用不到的索引。

5) 在 Btree index 中(InnoDB 使用 Btree),可以在需要排序的列上建立索引。

6) 避免重复的索引。

7) 避免在已有索引的前缀上建立索引。例如:如果存在 index(a,b)则去掉 index(a)。

8) 控制单个索引的长度。使用 key(name(8))在数据的前面几个字符建立索引。

9) 越是短的键值越好,最好使用 integer。

10) 在查询中要使用到索引(使用 explain 查看),可以减少读磁盘的次数,加速读取数据。

11) 相近的键值比随机好。Auto_increment 就比 uuid 好。

12) Optimize table 可以压缩和排序 index,注意不要频繁运行。

13) Analyze table 可以更新数据。

2.2 Designing queries

查询语句的优化是一个 Case by case 的问题,不同的 sql 有不同的优化方案,在这里我只列出一些通用的技巧。

1) 在有 index 的情况下,尽量保证查询使用了正确的 index。可以使用 EXPLAIN select …查看结果,分析查询。

2) 查询时使用匹配的类型。例如 select * from a where id=5,如果这里 id 是字符类型,同时有 index,这条查询则使用不到 index,会做全表扫描,速度会很慢。正确的应该是 … where id=”5”,加上引号表明类型是字符。

3) 使用 –log-slow-queries –long-query-time= 2 查看查询比较慢的语句。然后使用 explain 分析查询,做出优化。

3. 服务器端优化

3.1 MySQL 安装

MySQL 有很多发行版本,最好使用 MySQL AB 发布的二进制版本。也可以下载源代码进行编译安装,但是编译器和类库的一些 bug 可能会使编译完成的 MySQL 存在潜在的问题。

如果安装 MySQL 的服务器使用的是 Intel 公司的处理器,可以使用 intel c++ 编译的版本,在 Linux World2005 的一篇 PPT 中提到,使用 intel C++ 编译器编译的 MySQL 查询速度比正常版本快 30% 左右。Intel c++ 编译版本可以在 MySQL 官方网站下载。

3.2 服务器设置优化

MySQL 默认的设置性能很差,所以要做一些参数的调整。这一节介绍一些通用的参数调整,不涉及具体的存储引擎(主要指 MyISAM,InnoDB,相关优化在 4 中介绍)。

–character-set:如果是单一语言使用简单的 character set 例如 latin1。尽量少用 Utf-8,utf- 8 占用空间较多。

–memlock:锁定 MySQL 只能运行在内存中,避免 swapping,但是如果内存不够时有可能出现错误。

–max_allowed_packet:要足够大,以适应比较大的 SQL 查询,对性能没有太大影响,主要是避免出现 packet 错误。

–max_connections:server 允许的最大连接。太大的话会出现 out of memory。

–table_cache:MySQL 在同一时间保持打开的 table 的数量。打开 table 开销比较大。一般设置为 512。

–query_cache_size:用于缓存查询的内存大小。

–datadir:mysql 存放数据的根目录,和安装文件分开在不同的磁盘可以提高一点性能。

4. 存储引擎优化

MySQL 支持不同的存储引擎,主要使用的有 MyISAM 和 InnoDB。

4.1 MyISAM

MyISAM 管理非事务表。它提供高速存储和检索,以及全文搜索能力。MyISAM 在所有 MySQL 配置里被支持,它是默认的存储引擎,除非配置 MySQL 默认使用另外一个引擎。

4.1.1 MyISAM 特性

4.1.1.1 MyISAM Properties

1) 不支持事务,宕机会破坏表

2) 使用较小的内存和磁盘空间

3) 基于表的锁,并发更新数据会出现严重性能问题

4) MySQL 只缓存 Index,数据由 OS 缓存

4.1.1.2 Typical MyISAM usages

1) 日志系统

2) 只读或者绝大部分是读操作的应用

3) 全表扫描

4) 批量导入数据

5) 没有事务的低并发读 / 写

4.1.2 MyISAM 优化要点

1) 声明列为 NOT NULL,可以减少磁盘存储。

2) 使用 optimize table 做碎片整理,回收空闲空间。注意仅仅在非常大的数据变化后运行。

3) Deleting/updating/adding 大量数据的时候禁止使用 index。使用 ALTER TABLE t DISABLE KEYS。

4) 设置 myisam_max_[extra]_sort_file_size 足够大,可以显著提高 repair table 的速度。

4.1.3 MyISAM Table Locks

1) 避免并发 insert,update。

2) 可以使用 insert delayed,但是有可能丢失数据。

3) 优化查询语句。

4) 水平分区。

5) 垂直分区。

6) 如果都不起作用,使用 InnoDB。

4.1.4 MyISAM Key Cache

1) 设置 key_buffer_size variable。MyISAN 最主要的 cache 设置,用于缓存 MyISAM 表格的 index 数据,该参数只对 MyISAM 有影响。通常在只使用 MyISAM 的 Server 中设置 25-33% 的内存大小。

2) 可以使用几个不同的 Key Caches(对一些 hot data)。

a) SET GLOBAL test.key_buffer_size=512*1024;

b) CACHE INDEX t1.i1, t2.i1, t3 IN test;

2) Preload index 到 Cache 中可以提高查询速度。因为 preloading index 是顺序的,所以非常快。

a) LOAD INDEX INTO CACHE t1, t2 IGNORE LEAVES;

4.2 InnoDB

InnoDB 给 MySQL 提供了具有提交,回滚和崩溃恢复能力的事务安全 (ACID 兼容) 存储引擎。InnoDB 提供 row level lock,并且也在 SELECT 语句提供一个 Oracle 风格一致的非锁定读。这些特色增加了多用户部署和性能。没有在 InnoDB 中扩大锁定的需要,因为在 InnoDB 中 row level lock 适合非常小的空间。InnoDB 也支持 FOREIGN KEY 约束。在 SQL 查询中,你可以自由地将 InnoDB 类型的表与其它 MySQL 的表的类型混合起来,甚至在同一个查询中也可以混合。

InnoDB 是为在处理巨大数据量时获得最大性能而设计的。它的 CPU 使用效率非常高。

InnoDB 存储引擎已经完全与 MySQL 服务器整合,InnoDB 存储引擎为在内存中缓存数据和索引而维持它自己的缓冲池。InnoDB 存储它的表 索引在一个表空间中,表空间可以包含数个文件(或原始磁盘分区)。这与 MyISAM 表不同,比如在 MyISAM 表中每个表被存在分离的文件中。InnoDB 表可以是任何大小,即使在文件尺寸被限制为 2GB 的操作系统上。

许多需要高性能的大型数据库站点上使用了 InnoDB 引擎。著名的 Internet 新闻站点 Slashdot.org 运行在 InnoDB 上。Mytrix, Inc. 在 InnoDB 上存储超过 1TB 的数据,还有一些其它站点在 InnoDB 上处理平均每秒 800 次插入 / 更新的负荷。

4.2.1 InnoDB 特性

4.2.1.1 InnoDB Properties

1) 支持事务,ACID,外键。

2) Row level locks。

3) 支持不同的隔离级别。

4) 和 MyISAM 相比需要较多的内存和磁盘空间。

5) 没有键压缩。

6) 数据和索引都缓存在内存 hash 表中。

4.2.1.2 InnoDB Good For

1) 需要事务的应用。

2) 高并发的应用。

3) 自动恢复。

4) 较快速的基于主键的操作。

4.2.2 InnoDB 优化要点

1) 尽量使用 short,integer 的主键。

2) Load/Insert 数据时按主键顺序。如果数据没有按主键排序,先排序然后再进行数据库操作。

3) 在 Load 数据是为设置 SET UNIQUE_CHECKS=0,SET FOREIGN_KEY_CHECKS=0,可以避免外键和唯一性约束检查的开销。

4) 使用 prefix keys。因为 InnoDB 没有 key 压缩功能。

4.2.3 InnoDB 服务器端设定

innodb_buffer_pool_size:这是 InnoDB 最重要的设置,对 InnoDB 性能有决定性的影响。默认的设置只有 8M,所以默认的数据库设置下面 InnoDB 性能很差。在只有 InnoDB 存储引擎的数据库服务器上面,可以设置 60-80% 的内存。更精确一点,在内存容量允许的情况下面设置比 InnoDB tablespaces 大 10% 的内存大小。

innodb_data_file_path:指定表数据和索引存储的空间,可以是一个或者多个文件。最后一个数据文件必须是自动扩充的,也只有最后一个文件允许自动扩充。这样,当空间用完后,自动扩充数据文件就会自动增长 (以 8MB 为单位) 以容纳额外的数据。例如:innodb_data_file_path=/disk1/ibdata1:900M;/disk2/ibdata2:50M:autoextend 两个数据文件放在不同的磁盘上。数据首先放在 ibdata1 中,当达到 900M 以后,数据就放在 ibdata2 中。一旦达到 50MB,ibdata2 将以
8MB 为单位自动增长。如果磁盘满了,需要在另外的磁盘上面增加一个数据文件。

innodb_autoextend_increment: 默认是 8M, 如果一次 insert 数据量比较多的话, 可以适当增加.

innodb_data_home_dir:放置表空间数据的目录,默认在 mysql 的数据目录,设置到和 MySQL 安装文件不同的分区可以提高性能。

innodb_log_file_size:该参数决定了 recovery speed。太大的话 recovery 就会比较慢,太小了影响查询性能,一般取 256M 可以兼顾性能和 recovery 的速度。

innodb_log_buffer_size:磁盘速度是很慢的,直接将 log 写道磁盘会影响 InnoDB 的性能,该参数设定了 log buffer 的大小,一般 4M。如果有大的 blob 操作,可以适当增大。

innodb_flush_logs_at_trx_commit=2:该参数设定了事务提交时内存中 log 信息的处理。

1) = 1 时,在每个事务提交时,日志缓冲被写到日志文件,对日志文件做到磁盘操作的刷新。Truly ACID。速度慢。

2) = 2 时,在每个事务提交时,日志缓冲被写到文件,但不对日志文件做到磁盘操作的刷新。只有操作系统崩溃或掉电才会删除最后一秒的事务,不然不会丢失事务。

3) = 0 时,日志缓冲每秒一次地被写到日志文件,并且对日志文件做到磁盘操作的刷新。任何 mysqld 进程的崩溃会删除崩溃前最后一秒的事务

innodb_file_per_table:可以存储每个 InnoDB 表和它的索引在它自己的文件中。

transaction-isolation=READ-COMITTED: 如果应用程序可以运行在 READ-COMMITED 隔离级别,做此设定会有一定的性能提升。

innodb_flush_method:设置 InnoDB 同步 IO 的方式:

1) Default – 使用 fsync()。

2) O_SYNC 以 sync 模式打开文件,通常比较慢。

3) O_DIRECT,在 Linux 上使用 Direct IO。可以显著提高速度,特别是在 RAID 系统上。避免额外的数据复制和 double buffering(mysql buffering 和 OS buffering)。

innodb_thread_concurrency:InnoDB kernel 最大的线程数。

1) 最少设置为(num_disks+num_cpus)*2。

2) 可以通过设置成 1000 来禁止这个限制

5. 缓存

缓存有很多种,为应用程序加上适当的缓存策略会显著提高应用程序的性能。由于应用缓存是一个比较大的话题,所以这一部分还需要进一步调研。

 

以上就是如何优化 MYSQL 性能,丸趣 TV 小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注丸趣 TV 行业资讯频道。

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-01发表,共计7098字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)