mysql优化的基本原则和方向
一、我们可以且应该优化什么?
*
*
*
*
*
*
*
*
* 低寻道时间对数据库磁盘非常重要。对与大表,你可以估计你将需要log(行数)/log(索引块长度/3*2/(键码长度 + 数据指针长度))+1次寻到才能找到一行。对于有500000行的表,索引Mediun int类型的列,需要log(500000) / log(1024/3*2/(3 + 2))+1=4次寻道。上述索引需要500000*7*3/2=5.2M的空间。实际上,大多数块将被缓存,所以大概只需要1-2次寻道。
* 然而对于写入(如上),你将需要4次寻道请求来找到在哪里存放新键码,而且一般要2次寻道来更新索引并写入一行。
* 对于非常大的数据库,你的应用将受到磁盘寻道速度的限制,随着数据量的增加呈N log N数据级递增。
* 将数据库和表分在不同的磁盘上。在MySQL中,你可以为此而使用符号链接。
* 条列磁盘(RAID 0)将提高读和写的吞吐量。
* 带镜像的条列(RAID 0+1)将更安全并提高读取的吞吐量。写入的吞吐量将有所降低。
* 不要对临时文件或可以很容易地重建的数据所在的磁盘使用镜像或RAID(除了RAID 0)。
* 在Linux上,在引导时对磁盘使用命令hdparm -m16 -d1以启用同时读写多个扇区和DMA功能。这可以将响应时间提高5~50%。
* 在Linux上,用async (默认)和noatime挂载磁盘(mount)。
* 对于某些特定应用,可以对某些特定表使用内存磁盘,但通常不需要。
* 不要使用NFS磁盘(会有NFS锁定的问题)。
* 增加系统和MySQL服务器的打开文件数量。(在safe_mysqld脚本中加入ulimit -n #)。
* 增加系统的进程和线程数量。
* 如果你有相对较少的大表,告诉文件系统不要将文件打碎在不同的磁道上(Solaris)。
* 使用支持大文件的文件系统(Solaris)。
* 选择使用哪种文件系统。在Linux上的Reiserfs对于打开、读写都非常快。文件检查只需几秒种。
o 可在不同的操作系统和数据库之间移植。
o 适宜快速原型。
o 应该使用DBI/DBD接口。
o 比PERL易学。
o 使用比PERL少的资源。
o 通过升级到PHP4可以获得更快的速度。
o MySQL的原生接口。
o 较快并赋予更多的控制。
o 低层,所以必须付出更多。
o 较高层次,给你更多的时间来编写应用。
o 仍在开发中
o 运行在Windows和Unix上。
o 几乎可在不同的SQL服务器间移植。
o 较慢。MyODBC只是简单的直通驱动程序,比用原生接口慢19%。
o 有很多方法做同样的事。很难像很多ODBC驱动程序那样运行,在不同的领域还有不同的错误。
o 问题成堆。Microsoft偶尔还会改变接口。
o 不明朗的未来。(Microsoft更推崇OLE而非ODBC)
* ODBC
o 运行在Windows和Unix上。
o 几乎可在不同的SQL服务器间移植。
o 较慢。MyODBC只是简单的直通驱动程序,比用原生接口慢19%。
o 有很多方法做同样的事。很难像很多ODBC驱动程序那样运行,在不同的领域还有不同的错误。
o 问题成堆。Microsoft偶尔还会改变接口。
o 不明朗的未来。(Microsoft更推崇OLE而非ODBC)
o 理论上可在不同的操作系统何时据库间移植。
o 可以运行在web客户端。
o 可能不错,可我们不用它们。
* 在编写应用时,应该决定什么是最重要的:
o 速度
o 操作系统间的可移植性
o SQL服务器间的可移植性
* 使用持续的连接。.
* 缓存应用中的数据以减少SQL服务器的负载。
* 不要查询应用中不需要的列。
* 不要使用SELECT * FROM table_name...
* 测试应用的所有部分,但将大部分精力放在在可能最坏的合理的负载下的测试整体应用。通过以一种模块化的方式进行,你应该能用一个快速“哑模块”替代找到的瓶颈,然后很容易地标出下一个瓶颈。
* 如果在一个批处理中进行大量修改,使用LOCK TABLES。例如将多个UPDATES或DELETES集中在一起。
* ODBC
* JDBC
* Python(或其他有普遍SQL接口的语言)
* 你应该只使用存在于所有目的SQL服务器中或可以很容易地用其他构造模拟的SQL构造。www.mysql.com上的Crash-me页可以帮助你。
* 为操作系统/SQL服务器编写包装程序来提供缺少的功能。
* 使用给予你更快速度/灵活性的扩展。
* 逐渐了解SQL服务器以便能为你的问题使用可能最快的SQL构造并避免瓶颈。
* 优化表布局和查询。
* 使用复制以获得更快的选择(select)速度。
* 如果你有一个慢速的网络连接数据库,使用压缩客户/服务器协议。
* 位你的系统寻找最好的启动选项。
* 通读MySQL参考手册并阅读Paul DuBios的《MySQL》一书。(已有中文版-译注)
* 多用EXPLAIN SELECT、SHOW VARIABLES、SHOW STATUS和SHOW PROCESSLIST。
* 了解查询优化器的工作原理。
* 优化表的格式。
* 维护你的表(myisamchk、CHECK TABLE、 OPTIMIZE TABLE)
* 使用MySQL的扩展功能以让一切快速完成。
* 如果你注意到了你将在很多场合需要某些函数,编写MySQL UDF函数。
* 不要使用表级或列级的GRANT,除非你确实需要。
* 购买MySQL技术支持以帮助你解决问题
* 在Linux/Intel平台上,用pgcc(gcc的奔腾芯片优化版)编译MySQL。然而,二进制代码将只能运行在Intel奔腾CPU上。
* 对于一种特定的平台,使用MySQL参考手册上推荐的优化选项。
* 一般地,对特定CPU的原生编译器(如Sparc的Sun Workshop)应该比gcc提供更好的性能,但不总是这样。
* 用你将使用的字符集编译MySQL。
* 静态编译生成mysqld的执行文件(用--with-mysqld-ldflags=all-static)并用strip sql/mysqld整理最终的执行文件。
* 注意,既然MySQL不使用C++扩展,不带扩展支持编译MySQL将赢得巨大的性能提高。
* 如果操作系统支持原生线程,使用原生线程(而不用mit-pthreads)。
* 用MySQL基准测试来测试最终的二进制代码。
* 偶尔用myisamchk -a更新一下表中的键码分布统计。记住在做之前关掉MySQL。
* 如果有碎片文件,可能值得将所有文件复制到另一个磁盘上,清除原来的磁盘并拷回文件。
* 如果遇到问题,用myisamchk或CHECK table检查表。
* 用mysqladmin -i10 precesslist extended-status监控MySQL的状态。
* 用MySQL GUI客户程序,你可以在不同的窗口内监控进程列表和状态。
* 使用mysqladmin debug获得有关锁定和性能的信息。
* JOIN表
* GROUP BY
* ORDER BY
* DISTINCT
* 成为一只计算器
* 键码适合搜索,但不适合索引列的插入/更新。
* 保持数据为数据库第三范式,但不要担心冗余信息或这如果你需要更快的速度,创建总结表。
* 在大表上不做GROUP BY,相反创建大表的总结表并查询它。
* UPDATE table set count=count+1 where key_column=constant非常快。
* 对于大表,或许最好偶尔生成总结表而不是一直保持总结表。
* 充分利用INSERT的默认值。
mysql 367 249
mysql_odbc 464
db2_odbc 1206
informix_odbc 121126
ms-sql_odbc 1634
oracle_odbc 20800
solid_odbc 877
sybase_odbc 17614
插入350768行: NT Linux
mysql 381 206
mysql_odbc 619
db2_odbc 3460
informix_odbc 2692
ms-sql_odbc 4012
oracle_odbc 11291
solid_odbc 1801
sybase_odbc 4802
thread_cache_size 如果需要大量新连接,修改它。
key_buffer_size 索引页池,可以设成很大。
bdb_cache_size BDB表使用的记录和键吗高速缓存。
table_cache 如果有很多的表和并发连接,修改它。
delay_key_write 如果需要缓存所有键码写入,设置它。
log_slow_queries 找出需花大量时间的查询。
max_heap_table_size 用于GROUP BY
sort_buffer 用于ORDER BY和GROUP BY
myisam_sort_buffer_size 用于REPAIR TABLE
join_buffer_size 在进行无键吗的联结时使用。
* ANALYSE过程可以帮助你找到表的最优类型:SELECT * FROM table_name PROCEDURE ANALYSE()。
* 对于不保存NULL值的列使用NOT NULL,这对你想索引的列尤其重要。
* 将ISAM类型的表改为MyISAM。
* 如果可能,用固定的表格式创建表。
* 不要索引你不想用的东西。
* 利用MySQL能按一个索引的前缀进行查询的事实。如果你有索引INDEX(a,b),你不需要在a上的索引。
* 不在长CHAR/VARCHAR列上创建索引,而只索引列的一个前缀以节省存储空间。CREATE TABLE table_name (hostname CHAR(255) not null, index(hostname(10)))
* 对每个表使用最有效的表格式。
* 在不同表中保存相同信息的列应该有同样的定义并具有相同的列名。
* 表以文件存储。
* 列以变长或定长格式存储在文件中。对BDB表,数据以页面形式存储。
* 支持基于内存的表。
* 数据库和表可在不同的磁盘上用符号连接起来。
* 在Windows上,MySQL支持用.sym文件内部符号连接数据库。
* ISAM表:MySQL 3.22中的早期B-tree表格式。
* MyIASM:IASM表的新版本,有如下扩展:
o 二进制层次的可移植性。
o NULL列索引。
o 对变长行比ISAM表有更少的碎片。
o 支持大文件。
o 更好的索引压缩。
o 更好的键吗统计分布。
o 更好和更快的auto_increment处理。
* 来自Sleepcat的Berkeley DB(BDB)表:事务安全(有BEGIN WORK/COMMIT|ROLLBACK)。
* 定长格式比动态长度格式快很多并更安全。
* 动态长度行格式一般占用较少的存储空间,但如果表频繁更新,会产生碎片。
* 在某些情况下,不值得将所有VARCHAR、BLOB和TEXT列转移到另一个表中,只是获得主表上的更快速度。
* 利用myiasmchk(对ISAM,pack_iasm),可以创建只读压缩表,这使磁盘使用率最小,但使用慢速磁盘时,这非常不错。压缩表充分地利用将不再更新的日志表
* 表缓存:table_cache,默认64。
* 线程缓存:thread_cache_size,默认0。
* 主机名缓存:可在编译时修改,默认128。
* 内存映射表:目前仅用于压缩表。
* record_buffer:扫描表。
* join_buffer_size:无键联结
* myisam_sort_buffer_size:REPAIR TABLE
* net_buffer_length:对于读SQL语句并缓存结果。
* tmp_table_size:临时结果的HEAP表大小。
*
* 如果所有在高速缓存中的表都在使用,缓存将临时增加到比表缓存尺寸大些。如果是这样,下一个被释放的表将被关闭。
* 你可以通过检查mysqld的Opened_tables变量以检查表缓存是否太小。如果该值太高,你应该增大表高速缓存。
*
* 对数据使用优化的列。
* 如果可能使用定长行。
* 使用不同的锁定类型(SELECT HIGH_PRIORITY,INSERT LOW_PRIORITY)
* Auto_increment
* REPLACE (REPLACE INTO table_name VALUES (...))
* INSERT DELAYED
* LOAD DATA INFILE / LOAD_FILE()
* 使用多行INSERT一次插入多行。
* SELECT INTO OUTFILE
* LEFT JOIN, STRAIGHT JOIN
* LEFT JOIN ,结合IS NULL
* ORDER BY可在某些情况下使用键码。
* 如果只查询在一个索引中的列,将只使用索引树解决查询。
* 联结一般比子查询快(对大多数SQL服务器亦如此)。
* LIMIT
o SELECT * from table1 WHERE a > 10 LIMIT 10,20
o DELETE * from table1 WHERE a > 10 LIMIT 10
* foo IN (常数列表) 高度优化。
* GET_LOCK()/RELEASE_LOCK()
* LOCK TABLES
* INSERT和SELECT可同时运行。
* UDF函数可装载进一个正在运行的服务器。
* 压缩只读表。
* CREATE TEMPORARY TABLE
* CREATE TABLE .. SELECT
* 带RAID选项的MyIASM表将文件分割成很多文件以突破某些文件系统的2G限制。
* Delay_keys
* 复制功能
o SELECT * FROM table_name WHERE key_part1=1 and key_part2 > 5;
o SELECT * FROM table_name WHERE key_part1 IS NULL;
* 当使用不以通配符开始的LIKE
o SELECT * FROM table_name WHERE key_part1 LIKE 'jani%'
* 在进行联结时从另一个表中提取行时
o SELECT * from t1,t2 where t1.col=t2.key_part
* 找出指定索引的MAX()或MIN()值
o SELECT MIN(key_part2),MAX(key_part2) FROM table_name where key_part1=10
* 一个键码的前缀使用ORDER BY或GROUP BY
o SELECT * FROM foo ORDER BY key_part1,key_part2,key_part3
* 在所有用在查询中的列是键码的一部分时间
o SELECT key_part3 FROM table_name WHERE key_part1=1
o SELECT * FROM table_name where key_part1 > 1 and key_part1 < 90
* 如果使用HEAP表且不用=搜索所有键码部分。
* 在HEAP表上使用ORDER BY。
* 如果不是用键码第一部分
o SELECT * FROM table_name WHERE key_part2=1
* 如果使用以一个通配符开始的LIKE
o SELECT * FROM table_name WHERE key_part1 LIKE '%jani%'
* 搜索一个索引而在另一个索引上做ORDER BY
o SELECT * from table_name WHERE key_part1 = # ORDER BY key2
-> from t1 join t2 join t3
-> where t2.ID = t1.TransactionID and t3.ID = t2.GroupID
-> order by t3.DateOfAction, t1.TransactionID;
+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
| table | type | possible_keys | key | key_len | ref | rows | Extra |
+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
| t1 | ALL | NULL | NULL | NULL | NULL | 11 | Using temporary; Using filesort |
| t2 | ref | ID | ID | 4 | t1.TransactionID | 13 | |
| t3 | eq_ref | PRIMARY | PRIMARY | 4 | t2.GroupID | 1 | |
+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
使用SHOW processlist来发现正在做什么:
| Id | User | Host | db | Command | Time | State | Info |
+----+-------+-----------+----+---------+------+--------------+-------------------------------------+
| 6 | monty | localhost | bp | Query | 15 | Sending data | select * from station,station as s1 |
| 8 | monty | localhost | | Query | 0 | | show processlist |
+----+-------+-----------+----+---------+------+--------------+-------------------------------------+
运行项列命令并试图弄明白其输出:
* SHOW COLUMNS FROM ...\G
* EXPLAIN SELECT ...\G
* FLUSH STATUS;
* SELECT ...;
* SHOW STATUS;
* 在进行很多连接时,连接非常快。
* 同时使用SELECT和INSERT的场合。
* 在不把更新与耗时太长的选择结合时。
* 在大多数选择/更新使用唯一键码时。
* 在使用没有长时间冲突锁定的多个表时。
* 在用大表时(MySQL使用一个非常紧凑的表格式)。
* 在能放在WHERE子句中的列上用HAVING。
* 不使用键码或键码不够唯一而进行JOIN。
* 在不同列类型的列上JOIN。
* 在不使用=匹配整个键码时使用HEAP表。
* 在MySQL监控程序中忘记在UPDATE或DELETE中使用一条WHERE子句。如果想这样做,使用mysql客户程序的--i-am-a-dummy选项。
* LOCK TABLES(所有表类型适用)
* GET LOCK()/RELEASE LOCK()
* 页面锁定(对BDB表)
* ALTER TABLE也在BDB表上进行表锁定
* LOCK TABLES允许一个表有多个读者和一个写者。
* 一般WHERE锁定具有比READ锁定高的优先级以避免让写入方干等。对于不重要的写入方,可以使用LOW_PRIORITY关键字让锁定处理器优选读取方。
SELECT /*! SQL_BUFFER_RESULTS */ ...
将强制MySQL生成一个临时结果集。只要所有临时结果集生成后,所有表上的锁定均被释放。这能在遇到表锁定问题时或要花很长时间将结果传给客户端时有所帮助。
* SELECT SQL_SMALL_RESULT ... GROUP BY ...
告诉优化器结果集将只包含很少的行。
* SELECT SQL_BIG_RESULT ... GROUP BY ...
告诉优化器结果集将包含很多行。
* SELECT STRAIGHT_JOIN ...
强制优化器以出现在FROM子句中的次序联结表。
* SELECT ... FROM table_name [USE INDEX (index_list) | IGNORE INDEX (index_list)] table_name2
强制MySQL使用/忽略列出的索引。
mysql> select sum(value) from trans where customer_id=some_id;
mysql> update customer set total_value=sum_from_previous_statement
where customer_id=some_id;
mysql> UNLOCK TABLES;
mysql> select sum(value) from trans where customer_id=some_id;
mysql> update customer set total_value=sum_from_previous_statement
where customer_id=some_id;
mysql> COMMIT;
IF found-row
LOCK TABLES t1
DELETE FROM t1 WHERE key1=#
INSERT INTO t1 VALUES (...)
UNLOCK TABLES t1;
ENDIF
* 当使用多部分键码时,第一部分应该时最常用的部分。
* 有疑问时,首先使用更多重复的列以获得更好地键码压缩。
* 如果在同一台机器上运行MySQL客户和服务器,那么在连接MySQL时则使用套接字而不是TCP/IP(这可以提高性能7.5%)。可在连接MySQL服务器时不指定主机名或主机名为localhost来做到。
* 如果可能,使用--skip-locking(在某些OS上为默认),这将关闭外部锁定并将提高性能。
* 使用应用层哈希值而非长键码:
col_1='constant' AND col_2='constant'
* 删除所有行比删除一大部分行要快。
* 如果SQL不够快,研究一下访问数据的较底层接口。
* HEAP:内存中的表
* Berkeley DB:支持事务的表。
* 众多提高的限制
* 动态字符集
* 更多的STATUS变量
* CHECK和REPAIR表
* 更快的GROUP BY和DISTINCT
* LEFT JOIN ... IF NULL的优化
* CREATE TABLE ... SELECT
* CREATE TEMPORARY table_name (...)
* 临时HEAP表到MyISAM表的自动转换
* 复制
* mysqlhotcopy脚本
* 失败安全的复制
* 正文搜索
* 多个表的删除(之后完成多个表的更新)
* 更好的键码缓存
* 原子RENAME (RENAME TABLE foo as foo_old, foo_new as foo)
* 查询高速缓存
* MERGE TABLES
* 一个更好的GUI客户程序
转载于:https://blog.51cto.com/dason/360704
mysql优化的基本原则和方向相关推荐
- MySQL优化学习总结
MySQL 性能优化的最佳20多条经验分享 http://www.jb51.net/article/24392.htm 今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关 ...
- mysql优化说出九条_技术分享 | MySQL 优化:为什么 SQL 走索引还那么慢?
原标题:技术分享 | MySQL 优化:为什么 SQL 走索引还那么慢? 背景 2019-01-11 9:00-10:00 一个 MySQL 数据库把 CPU 打满了. 硬件配置:256G 内存,48 ...
- Mysql 优化器内部JOIN算法hash join On-Disk Hash Join Grace Hash Join Hybrid hash join过程详解
Mysql 各种hash join算法讲解 hash join的概述 提到hash join之前自然得说Nest loop join,以两个表的关联为例,它其实是个双层循环,先遍历外层的表(n条),再 ...
- Mysql 优化的一些要点
本文是学习<高性能 Mysql>中关于 Mysql 中查询优化需要注意的一些要点的总结: Schema 和数据类型优化 尽量避免使用 NULL 值,尤其存在索引时,因为如果 NULL 列是 ...
- mysql优化 运维_MySQL运维---MySQL优化
一.优化 1.优化的角度 2.优化的方向 3.数据库优化思路 4.MySQL优化介绍 5.优化工具介绍 二.操作系统优化 1.top命令 1)CPU 2)内存 3)slab分配器---Linux内存 ...
- mysql 优化方法有哪些?
MySQL索引 MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等.为了避免混乱,本文将只关注于BTree ...
- 关于mysql优化_关于MySQL优化的几点总结
前言 现如今,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.所以,我整理了MySQL优化的几点建议,希望这些优化技巧对您有用,总结不到的,欢迎大家补充. SQL执行慢的原因 ...
- mysql优化要点_你需要掌握的 Mysql 优化的一些要点
本文是学习<高性能 Mysql>中关于 Mysql 中查询优化需要注意的一些要点的总结: Schema 和数据类型优化尽量避免使用 NULL 值,尤其存在索引时,因为如果 NULL 列是索 ...
- 关于MySQL优化的几个问题
本文来说下关于MySQL优化的几个问题 文章目录 概述 SQL优化 分页优化 索引优化 Join优化 排序优化 UNION优化 慢查询日志 设计优化 常见类型选择 范式化 硬件优化 本文小结 概述 M ...
- php数据库--mysql优化
mysql优化概述: mysql优化概述方针:① 存储层:数据表"存储引擎"选取.字段类型选取.逆范式(3范式)② 设计层:索引.分区/分表.存储过程,sql语句的优化③ 架构层: ...
最新文章
- Titanium开发环境搭建第一个坑
- 一项调查结果:你的分析/挖掘计算机的配置
- MyEclipse生成Javadoc帮助文档
- 解决Vue报错:Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation to current location
- 拼多多年货节上线,“百亿补贴”加码iPhone 12等产品
- 虚拟机安装VMware ESXi 6.7安装过程介绍
- Java 获取日期间的日期 根据日期获取星期
- python里常用的正则表达式
- pve 虚拟环境 vi/vim不能右键粘贴设置方法
- Linux查看ip 地址命令(ip addr)
- PSP自制程序打包ISO方法及注意事项
- 图像处理中的一阶偏导数和二阶偏导数
- 【AI人工智能学习】GitHub 上适合初学者的 10 个最佳开源 AI 项目
- pest分析和swot分析的区别
- Egret 使用Texture Merger制作美术字体
- Android项目实战--手机卫士35--清除程序缓存
- 数据治理系列:浅谈数据质量管理
- 高频交易系统性能应该从哪些方面优化?
- 竞价排名和php是什么,php做seo优化-竞价与查找引擎优化的差异是什么
- nofollow标签的作用有重大变化
热门文章
- gridview分组android,安卓使用GridView实现网格视图
- 201771010112罗松《面向对象程序设计(java)》第十周学习总结
- Leetcode669.Trim a Binary Search Tree修建二叉树
- 安装opencv_contrib(ubuntu16.0)
- 整合Spring Data JPA与Spring MVC: 分页和排序pageable
- 几篇QEMU/KVM代码分析文章
- 通过Windows Live Writer发布日志到各大博客
- Host localhost is not allowed to connect to mysql server解决方法
- E60的存储空间不足? NO
- 如何进行各种码制数据之间转换