MySQL采取的是客户/做事器体系构造,因此实际利用时,有两个程序:
1. 一个是MySQL做事器程序,指的是mysqlId程序,运行在数据库做事器上,卖力在网络上监听并处理来自客户真个做事要求根据这些要求去访问数据库的内容,再把有关信息回传给客户;
2. 另一个程序是MySQL客户端程序,卖力连接到数据库做事器,并通过发出命令来奉告做事器它想要的操作。
从下面大略的逻辑图中可以看出,MySQL内部大致分为三层:
1. 最上层是大部分基于网络的C/S做事都有的部分,比如连接处理、授权认证、安全等;
2. 第二层包括MySQL的很多核心做事功能,包括查询解析、剖析、优化、缓存以及所有的内置函数(例如,日期、韶光、数学和加密函数),所有的跨存储引擎的功能都在这一层实现:存储过程、触发器、视图等。
3. 第三层包含了存储引擎,存储引擎卖力MySQL中欧数据的存储和提取,是数据库中非常主要非常核心的部分,也是MySQL差异与其他数据库的一个主要特性。
不同的存储引擎有个字的特点,MySQL支持插入式的存储引擎,可以根据实际情形选择最得当的存储引擎。不过目前对付绝大部分运用来说,MySQL默认的存储引擎InnoDB该当便是其最佳选择。我以为刚开始学习的时候先容很多不常用乃至不会用到的存储引擎虽然可能会横向比较,让开发职员更理解每个存储引擎的特性,但是这样对开拓职员造成的困扰更大,还不如专心学习一种用场最广泛的存储引擎,屏蔽其他滋扰,学到一定深度后再理解其他存储引擎的不同点。
2、体系构造
详细查看MySQL在物理上的体系构造,从上到下依次是:
1. 连接池组件
2. 管理做事和工具组件、SQL接口组件、查询剖析器组件、优化器组件、缓冲组件
3. 插件式存储引擎
4. 物理文件
三、 数据库和实例区分两个词
数据库指物理上的存储文件,实例是用来操作数据库文件的。在MySQL数据库中,实例与数据库常日是逐一对应的,这时两个词可以互换,但在集议论形下,可能存在一个数据库被对个数据实例利用的情形.
MySQL是单进程多线程架构的数据库,实例在系统上的表现便是一个进程。
四、MySQL不得不说的八个陷阱Mysql安装大略,速率较快,功能丰富。其余它还是开源运动的标杆,它的伟大造诣向我们展示了一个成功的公司是可以建立在开源代码之上的。
然而用过mysql的人都曾对着显示器摆荡过拳头。但你不可能发明一种每秒能保存成千上万行互联网数据,并且一点缺点都没有的技能吧。
以下列举了8个开源关系型数据库的毛病,个中不仅限于MySQL,还有是针对关系型数据库的。只有明白了关系型数据库和MySQL,才能更好地避免在利用MySQL中只管即便少地碰着一些意外。
1、根深蒂固的bugs
任何大的软件包都有 bug。但轻微深入理解一下,就会创造和 Mysql 干系的 bugs 自成体系。溘然你就须要把稳,由于 NULL 并不因此同样的办法涌现,外键约束也没有像你想像的那样实行,连主键自动增长也会出错。
小问题大量存在,而且并不总是可以修复,这便是为什么一些人保持一个列表。还好 MySQL 掩护着一个非常好的 bug 报告系统,让我们可以知道我些我们无法想像的事情,知道其他人也在经受同样的磨难。
2、关系表的不灵巧性
关系表具有条理性,条理性是好的——但是,它使得程序员不得不编造或硬塞一些数据到已经定义好模式的列中。NoSQL开始越来越受到欢迎的缘故原由之一,便是它为程序员供应了足够的灵巧性,来加速数据库的利用。如果一个街道地址须要增加一行,那么,你可以将它很随意马虎地插入到一个NoSQL文档中。如果你想添加一个完全的新的数据块,无论它包含什么内容,文档模型也可以原封不动地接管你的数据,而不必改为它哀求的数据格式。
试想一下,你用整数格式建立了一个全部是邮编的表格。这个表是十分高效的,它实行的规则也很好。溘然一次,有人上传了一个利用了连字符的九位数邮编。或者还有可能,你得到了一位来自加拿大客户的信件,上面写有邮政编码。
这时,统统都乱了。老板哀求网站要在几小时内规复正常事情。然而,现在已经没有韶光来重修数据库。程序员可以做什么?大概,可以利用黑客手段把加拿大邮政编码由base64的数字格式改为base 10格式?或者设置一个利用转义编码的赞助表格,用来解释真正的邮政编码或者其他?谁知道呢?到处都有黑客,他们都是危险的。但你没有韶光来搞定它。
MySQL的关联规则让每个人都老实和谨慎,但它能逼迫我们避开易受攻击和欺骗的麻烦。
3、存储引擎混乱
总体来说,Mysql的存储引擎接口定义还算良好的。MySQL不是实际上的同一的数据库。它是由几个数据库组成,它们的大多数细节都被统一的表面粉饰了。开始时有一个MyISAM引擎,它很快但在前后同等上不能做到完备。有时你须要速率并且可以接管不一致的结果时是很好的。
当人们须要更多时,具备完全事务支持的Inno DB涌现了。但这还不足。现在,它可能有20种存储引擎的选择——这足以使一个数据库管理员猖獗。当然,有时在不同的存储引擎之间切换而不必重写你的SQL是很好的,但是切换后总会带来混乱。这个表格我选择的引擎是MyISAM还是innoDB呢?或者,我决定输出的数据是CSV格式的吗?
4、JOIN联合查询
曾经,将数据分表保存是打算机科学史上的伟大创新。分开后的表不仅构造大略,利用上也简化了许多。但它却须要利用join语句来进行查询。
sql通过一系列join构建的繁芜查询将开拓者推入了困惑与绝望的深渊。而且存储引擎也须要以最优的办法来高效地解析join语句。开拓者须要绞尽脑汁编写查询语句,然后数据库对其进行解析。
这便是很多看重运行速率的开拓者放弃数据分表转而利用不规范数据表的缘故原由。不区分数据实体,将所有数据保存到一个大表中——以避免繁芜的查询。这样确实很快,并且做事器也不会耗尽内存。
现在的磁盘空间很廉价。8TB的磁盘已经在售,更大容量的也将上市。我们不再须要为利用join而绞尽脑汁了。
5、分支的混乱
毋庸置疑,一个可靠的、得到良好支持的MySQL分支,可以带来竞争和选择,但是它也引起困惑和混乱。更糟糕的是,一个称为MariaDB的MySQL分支,由Monty Widenius掩护着。他同样也在参与编写MySQL。那么,Maria DB是真正独立的值得我们推戴的吗?或者它是MySQL?我们是否该当坚持利用由创建原始mysql数据库的组织运营的核心代码?或者我们该当加入那些被认为更聪明的,每每很酷的背叛者?
如何获取关于兼容性的信息?虽然Maria DB和MySQL十分相似,但它们之间也有差异。这便是大家一贯都在辩论它的缘故原由。在性能方面,在我们查询的范围内,在两个阵营中,大概它们的事情办法相同,但大概不同,大概将来会不同。
6、开拓MySQL的动机
虽然MySQL是一款成功的开源产品,但它仍属于商业中的一款产品,专业开拓者须要靠它来得到利益,当然,最直接的利益便是薪资。昔时夜多数用户在持续地享受开源容许证带来的最佳体验时,毫无疑问这家公司还在为赚取足够的钱来坚持运营而努力。这导致自由代码在“社区版”和出售给企业的完全产品之间产生了奇怪的分岐。
我们该当对这款产品付钱吗?这种在社区版开展经营的行为是否公正?企业版中额外的功能是不是一个噱头,以领导我们不断付费的呢?这至少解释一点,它是另一些须要回答的问题:选用哪个版本?遵照哪种容许证?选用它的哪个功能集?
7、原生JSON支持的缺少
通过安装MySQL查看其年事,然后你就知道须要添加哪些驱动程序使它变得可用。MySQL常日在3306端口上通信,一样平常输出的是它本身难以理解的格式化数据。如果要让你的代码和它通信,你必须添加另一层代码,将MySQL的措辞转换成有用的东西。这些层的代码,以库的形式分发,常常须要人们购买一个商业容许证。
当代数据存储层常日直接以JSON通信。虽然MySQL和Maria DB现在有能力解析SQL中的JSON部分,但这还远远不足,原生的JSON接口已经被广泛利用于CouchDB、MongoDB,或任何最新的工具中。
8、封闭源和专有模块的兴起
虽然MySQL是开源的,但除了一些在”开源核心“周边开拓的一些较新的、非开源的代码和专有模块。程序员也须要赢利、须要生活,Oracle须要拿它的辛劳成果来换钱,这是一种现实,也是商业的性子。利用MySQL你也不可以免费得到任何东西。
哀求MySQL始终坚持在一个很高的标准上,这有点不公正,由于开源的成功可能是一个圈套。它开始可以免费,但并不虞味着它可以始终免费。如果企业须要更多新的功能,他们就要通过各种办法付费来获取。有时向Oracle付费,比自己来编写代码要便宜得多。有时商业的、不开源的代码是故意义的。
MySQL虽然作为一个成功的开源系统,但以上这些问题也总不可避免地涌现,这就须要我们在它们发生之前有个深刻的认识,才能在今后的运用中避免不必要的麻烦。
在此我向大家推举一个架构学习互换群。互换学习群号:575745314 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码剖析,高并发、高性能、分布式、微做事架构的事理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多
五、MySQL分布式集群搭建1 准备集群搭建环境
利用6台虚拟机来搭建MYSQL集群,相应的实验环境与对应的MYSQL节点之间的对应关系如下图所示:
管理节点(MGM):这类节点的浸染是管理MySQLCluster内的其他节点,如供应配置数据,并停滞节点,运行备份等。由于这类节点卖力管理其他节点的配置,该当在启动其他节点之前启动这类节点。MGM节点是用命令“ndb_mgmd”启动的;
数据节点(NDB):这类节点用于保存Cluster的数据,数据节点的数目与副本的数目干系,是片段的倍数。例如,对付两个副本,每个副本有两个片段,那么就有4个数据节点,没有必要设定过多的副本,在NDB中数据会只管即便的保存在内存中。数据节点利用命令“ndb”启动的;
SQL节点:这是用来访问Cluster数据的节点,对付MySQL Cluster,客户端节点是利用NDB Cluster存储引擎的传统MySQL做事器。常日,SQL节点利用命令“mysqld-ndbcluster”启动的;
2、准备安装包
在官网高下载mysql的安装包: mysql-cluster-gpl-7.4.11-Linux-glibc2.5-x86_64.tar.gz,并进行解压。
3、集群搭建流程
1]将上述安装包解压出来的文件都移到/usr/local/mysql下;
2]运行script目录下的mysql-install-db.sh脚本,运行命令为./mysql-install-db.sh --user=root--basedir =/usr/local/mysql --datadir=/usr/local/mysql;把稳个顶用户为root的名称须要跟配置文件my.cnf中的相同;
在管理节点,数据节点,SQL节点上都实行上述安装命令,从而完成对mysql的安装;
4、集群配置与启动
1]在管理节点上须要完成对付集群整体的配置配置:在/var/lib/mysql-cluster/config.ini中实现如下的配置信息:
2]在数据节点中须要在my.cnf中完成对付数据节点的干系配置信息,如下:
须要指明配置的数据节点的根目录,数据目录,socket连接配置,用户配置,以及对应的管理节点的ip地址配置;将配置完成的配置文件移动到/etc/my.cnf,完成;
3]在SQL节点上完成对付SQL节点的配置信息,同样的是在my.cnf中完成相应配置信息,并将配置文件移动到/etc/my.cnf中,相应的配置信息的设定如下所示:
完成以上配置后,就可以启动集群中的各个节点了。
5、集群启动
在启动mysql集群的时候,把稳首先要启动管理节点,并依次启动其他等多少个节点,相应的启动步骤如下:
1]在管理节点上,切换到/usr/local/mysql/bin目录下,实行ndb_mgmd -f /var/lib/mysql-cluster/config.ini命令,完成管理节点的启动;
2]在各个数据节点上,切换到/usr/local/mysql/bin目录下,实行ndbd --initial(第一次启动时,否则实行ndbd即可),完成对数据节点的启动;
3]在各个SQL节点上,同样切换到/usr/local/mysql/bin目录下,实行mysqld_safe --user=root完成启动;
4]在管理节点上运行ndb_mgm命令,进入数据库管理的客户端,输入show命令,查看与之相连接的各个节点的状态;
5]在SQL节点上分别进入系统的安全状态,并完成对root用户的密码修正,运行以下指令,进行密码修正:
A use mysql,切换到mysql数据库;
B UPDATE user SET Password = PASSWORD('123456')WHERE user = 'root';从而实现对root密码的修正;
C flush privilege,完成修正;
6]修正使得任意主机都能连得上mysql,进行如下修正,同样安装第5步进入安全模式,并完成相应的修正,如下:
grant all on‘.’to ‘root@'%' identified by '123456';
这样就可以使得任意一个主机都可以通过root用户来登录mysql了;
6、集群测试
在集群上的一个SQL节点上实行创建数据库,并创建一张表,并完成相应的数据插入,如下:
A create database ctest; //创建数据库
B create table test(
id int primarykey; //创建一张表
);
C insert into test (id)values(1); //完成数据插入
登录其余一个SQL节点,并实行SQL查询操作,看数据库中是否已经有数据,如下:
select from ctest;
如果有数据,表示数据插入成功;
7、关闭集群
1]首先关闭管理节点和数据节点,须要在管理节点上实行命令,如下:./ndb_mgm -e shutdown;
2]然后关闭SQL节点,在SQL节点上实行命令/usr/local/mysql/support-fies/mysql.server stop(个中/usr/local/mysql/是mysql的安装目录).从而关闭SQL节点
在此我向大家推举一个架构学习互换群。互换学习群号:575745314 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码剖析,高并发、高性能、分布式、微做事架构的事理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多
六、MySQL 的最佳实践
数据库操作是当今 Web 运用程序中的紧张瓶颈。 不仅是 DBA(数据库管理员)须要为各种性能问题操心,程序员为做出准确的构造化表,优化查询性能和编写更优代码,也要费尽心思。 在本文中,我列出了一些针对程序员的 MySQL 优化技能。
在我们开始学习之前,我补充一点:你可以在 Envato Market 上找到大量的 MySQL 脚本和实用程序。
1.优化查询的查询缓存
大部分MySQL做事器都有查询缓存功能。这是提高性能的最有效的方法之一,这是由数据库引擎私下处理的。当同一个查询被多次实行,结果会直接从缓存里提取,这样速率就很快。
紧张的问题是,这对程序员来说太大略了,不随意马虎看到,我们很多人都随意马虎忽略。我们实际上是可以组织查询缓存实行任务的。
查询缓存在第一行不实行的缘故原由在于CURDTE()功能的利用。这适用于所有的非确定性功能,就像NOW()和RAND()等等。。。由于功能返回的结果是可变的。MySQL决定禁用查询器的查询缓存。我们所须要做的是通过添加一额外一行PHP,在查询前阻挡它发生。
2. EXPLAIN你的选择查询
利用EXPLAIN关键词可以帮助理解MySQL是若何运行你的查询的。这有助于创造瓶颈和查询或表构造的其它问题。
EXPLAIN的查询结果会展示哪一个索引被利用过,表示若何扫描和储存的,等等。。。
选择一个SELECT查询(一个有连接的繁芜查询会更好),在它的前面添加关键词EXPLAIN,这样就可以直策应用数据库了。结果会以一个俊秀的表来展示。例如,就好比我实行连接时忘了添加一栏的索引:
现在它只会从表2里面扫描9和16行,而非扫描7883行。履历法则是乘以所有“行”那一栏的数字,你的查询性能会跟结果数字成比例的。
3. 获取唯一行时利用LIMIT 1
有时当你查表时,你已经知道你正在查找的结果只有一行。你可能正在获取唯一记录,或者你可能只是查询是否存在知足你的WHERE子句条件的记录。
在这种情形下,将LIMIT 1添加到查询条件中可以提高性能。这样,数据库引擎将在找到刚刚第一个记录之后停滞扫描记录,而不是遍历全体表或索引。
4. 索引搜索字段
索引不仅仅是为了主键或唯一键。如果你会在你的表中按照任何列搜索,你就都该当索引它们。
正如你所看到的,这个规则也适用于如 “last_name LIKE ‘a%’”的部分字符串搜索。当从字符串的开头搜索时,MySQL就可以利用那一列的索引。
你也该当明白什么样搜索可以不该用有规律的索引。例如,当搜索一个单词时(例如,”WHERE post_content LIKE ‘%apple%’”),你将不会看到普通索引的好处。你最好利用 mysql 全文搜索或者构建你自己的索引办理方案。
5. 索引并对连接利用同样的字段类型
如果你的运用程序包含许多连接查询, 你须要确保连接的字段在两张表上都建立了索引。 这会影响MySQL如何内部优化连接操作。
此外,被连接的字段,须要利用同样类型。例如, 如果你利用一个DECIMAL字段, 连接另一张表的INT字段, MySQL将无法利用至少一个索引。 纵然字符编码也须要利用相同的字符类型。
6. 不要ORDER BY RAND()
起初这是一个听起来挺酷的技巧, 让许多菜鸟程序员陷入了这个陷阱。但你可能不知道,一旦你开始在查询中利用它,你创建了非常恐怖的查询瓶颈。
如果你真的须要对结果随机排序, 这有一个更好的方法。补充一些额外代码,你将可以防止当数据成指数级增长时造成的瓶颈。关键问题是,MySQL必须在排序之前对表中的每一行实行RAND()操作(这须要处理能力),并且仅仅给出一行。
以是挑选一个小于结果数的随机数,并将其用作LIMIT子句中的偏移量。
7. 避免利用SELECT
从数据表中读取的数据越多,查询操作速率就越慢。它增加了磁盘操作所需的韶光。此外,当数据库做事器与Web做事器分开时,由于必须在做事器之间传输数据,将会有更长的网络延迟。
这是一个好习气:当你利用SELECT语句时总是指定你须要的列。
8. 险些总是有一个id字段
在每个以id列为PRIMARY KEY的数据表中,优先选择AUTO_INCREMENT或者INT。 也可以优选利用UNSIGNED,由于该值不能为负的。
纵然你拥有一个具有唯一用户名字段的用户表,也不要将其作为主键。 VARCHAR字段作为主键(检索)速率较慢。通过内部ID引用所有的用户数据,你的代码中将更加构造化。
有些后台操作是由MySQL引擎本身完成的,它在内部利用主键字段。当数据库设置越繁芜(集群,分区等…),这就变得更加主要了。
这个规则的一个可能的例外是“关联表”,用于两个表之间的多对多类型的关联。例如,“posts_tags”表中包含两列:post_id,tag_id,用于保存表名为“post”和“tags”的两个表之间的关系。这些表可以具有包含两个id字段的PRIMARY键。
9. 比较VARCHAR优先利用ENUM
ENUM列举类型是非常快速和紧凑的。在内部它们像TINYINT一样存储,但它们可以包含和显示字符串值。这使他们成为某些领域的完美候选。
如果有一个字段只包含几种不同的值,请利用ENUM而不是VARCHAR。例如,它可以是名为“status”的列,并且只包含诸如“active”,“inactive”,“pending”,“expired”等的值…
关于如何重构你的数据表,乃至有一种方法是可以从MySQL本身得到“建议”。 当你有一个VARCHAR字段,它实际上建议你将该列类型变动为ENUM。这通过调用PROCEDURE ANALYZE()来完成。
在此我向大家推举一个架构学习互换群。互换学习群号:575745314 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码剖析,高并发、高性能、分布式、微做事架构的事理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多
10. 利用PROCEDURE ANALYSE()获取建议
PROCEDURE ANALYSE() 将利用MySQL剖析列构造和表中的实际数据,为你供应一些建议。它只有在数据表中有实际数据时才有用,由于这在剖析决策时很主要。
例如,如果你创建了一个INT类型的主键,但没有太多行,MySQL则可能建议您改用MEDIUMINT。或者如果你利用VARCHAR字段,如果表里只有很少的取值,你可能会得到一个建议是将其转换为ENUM。
你也可以在个中一个表视图中单击phpmyadmin中的“建议表构造”链接来实行此操作。
请记住,这些只是建议。 如果你的数据表变得越来越大,他们乃至可能不是精确的建议。至于如何修正终极是你来决定。
11. 如果可以的话利用NOT NULL
除非你有非常主要的情由利用NULL值,否则你该当设置你的列为NOT NULL。
首先,问一下你自己在空字符串值和NULL值之间(对应INT字段:0 vs. NULL)是否有任何的不同.如果没有情由一起利用这两个,那么你就不须要一个NULL字段(你知道在Oracle中NULL和空字符串是一样的吗?)。
NULL列须要额外的空间,他们增加了你的比较语句的繁芜度。如果可以的话只管即便避免它们。当然,我理解一些人,他们大概有非常主要的情由利用NULL值,这不总是一件坏事。
摘自MySQL 文档:
“行空列须要额外的空间来记录它们的值是否为空。 对付MyISAM表,每个NULL列须要一点额外的,围捕到最近的字节”。
12. 预处理语句
利用预处理语句有诸多好处,包括更高的性能和更好的安全性。
预处理语句默认情形下会过滤绑定到它的变量,这对付避免SQL注入攻击极为有效。当然你也可以指定要过滤的变量。但这些方法更随意马虎涌现人为缺点,也更随意马虎被程序员遗忘。这在利用框架或 ORM 的时候会涌现一些问题。
既然我们关注性能,那就该当说说这个方面的好处。当在运用中多次利用同一个查询的时候,它的好处特殊明显。既然向同一个预备好的语句中传入不同的参数值,MySQL 对这个语句也只会进行一次解析。
同时,最新版本的 MySQL 在传输预备好的语句时会采取二进制形式,这样做的浸染非常明显,而且对减少网络延迟很有帮助。
曾经有一段韶光,许多程序员为了一个主要的缘故原由则避免利用预处理语句。这个缘故原由便是,它们不会被MySQL 缓存。不过在 5.1 版本的某个时候,查询缓存也得到的支持。
想在 PHP 中利用预处理语句,你可以看看 mysqli 扩展 或利用数据抽象层,如 PDO。
13. 无缓冲查询
常日当你从脚本实行一个查询,在它可以连续后面的任务之前将须要等待查询实行完成。你可以利用无缓冲的查询来改变这一情形。
在PHP 文档中对 mysql_unbuffered_query() f函数有一个很好的阐明:
“mysql_unbuffered_query()发送SQL查询查询MySQL没有自动抓取和缓冲结果行mysql_query()。 这节省了大量的内存生产大型结果集的SQL查询,你可以在结果集后立即开始事情第一行被检索到的是你不必等到完全的SQL查询已经完成。”
然而,它有一定的局限性。你必须在实行另一个查询之前读取所有的行或调用mysql_free_result() 。其余你不能在结果集上利用mysql_num_rows() 或 mysql_data_seek() 。
14. 利用 UNSIGNED INT 存储IP地址
很多程序员没故意识到可以利用整数类型的字段来存储 IP 地址,以是一贯利用 VARCHAR(15) 类型的字段。利用 INT 只须要 4 个字节的空间,而且字段长度固定。
必须确保列是 UNSINGED INT 类型,由于 IP 地址可能会用到 32 位无符号整型数据的每一个位。
在查询中可以利用 INET_ATON() 来把一个IP转换为整数,用 INET_NTOA() 来进行相反的操作。在 PHP 也有类似的函数,ip2long() 和 long2ip()。
15. 固定长度(静态)的表会更快
(译者注:这里提到的表的长度,实际是指表头的长度,即表中每条数据占用的空间大小,而不是指表的数据量)
如果表中所有列都是“固定长度”,那么这个表被认为是“静态”或“固定长度”的。不固定的列类型包括 VARCHAR、TEXT、BLOB等。纵然表中只包含一个这些类型的列,这个表就不再是固定长度的,MySQL 引擎会以不同的办法来处理它。
固定长度的表会提高性能,由于 MySQL 引擎在记录中检索的时候速率会更快。如果想读取表中的某一地,它可以直接打算出这一行的位置。如果行的大小不固定,那就须要在主键中进行检索。
它们也易于缓存,崩溃后随意马虎重修。不过它们也会占用更多空间。例如,如果你把一个 VARCHAR(20) 的字符改为 CHAR(20) 类型,它会总是占用 20 个字节,不管里面存的是什么内容。
你可以利用“垂直分区”技能,将长度变革的列拆分到另一张表中。来看看:
16. 垂直分区
垂直分区是为了优化表构造而对其进行纵向拆分的行为。
示例 1: 你可能会有一张用户表,包含家庭住址,而这个不是一个常用数据。这时候你可以选择把表拆分开,将住址信息保存到另一个表中。这样你的主用户表就会更小。如你所知,表越小越快。
示例 2: 表中有一个 “last_login” 字段,用户每次登录网站都会更新这个字段,而每次更新都会导致这个表缓存的查询数据被清空。这种情形下你可以将那个字段放到另一张表里,保持用户表更新量最小。
不过你也须要确保不会常常联合查询分开后的两张表,要不然你就得忍受由这带来的性能低落。
17. 拆分大型DELETE或INSERT语句
如果你须要在网站上实行大型DELETE或INSERT查询,则须要把稳不要影响网络流量。当实行大型语句时,它会锁表并使你的Web运用程序停滞。
Apache运行许多并行进程/线程。 因此它实行脚本效率很高。以是做事器不期望打开过多的连接和进程,这很花费资源,特殊是内存。
如果你锁表很永劫光(如30秒或更长),在一个高流量的网站,会导致进程和查询堆积,处理这些进程和查询可能须要很永劫光,终极乃至使你的网站崩溃。
如果你的掩护脚本须要删除大量的行,只需利用LIMIT子句,以避免壅塞。
18.越少的列越快
对付数据库引擎,磁盘可能是最主要的瓶颈。更小更紧凑的数据、减少磁盘传输量,常日有助于性能提高。
MySQL文档Storage Requirements 有所有数据类型清单。
如果已知表具有很少的行,则没有情由是主键类型为INT,可以用MEDIUMINT、SMALLINT代替,乃至在某些情形下利用TINYINT。 如果不须要完全韶光记录,请利用DATE而不是DATETIME。
确保留下合理的扩展空间,不然你可能会像Slashdot这样。
19. 选择精确的存储引擎
MySQL有两个紧张存储引擎,MyISAM和InnoDB。 每个都有自己的优点和缺陷。
MyISAM适用于读取繁重的运用程序,但是当有很多写入时它不能很好地扩展。 纵然你正在更新一行的一个字段,全体表也被锁定,并且在语句实行完成之前,其他进程乃至无法读取该字段。 MyISAM在打算SELECT COUNT()的查询时非常快。
InnoDB是一个更繁芜的存储引擎,对付大多数小的运用程序,它比MyISAM慢。 但它支持基于行的锁定,使其更好地扩展。 它还支持一些更高等的功能,比如事务。
● MyISAM存储引擎
● InnoDB存储引擎
20. 利用工具关系映射器(ORM, Object Relational Mapper)
通过利用ORM(工具关系映射器),你可以得到一定的性能提升。ORM可以完成的统统事情,手动编码也可完成。但这可能意味着须要太多额外的事情,并且须要高水平的专业知识。
ORM以“延迟加载”著称。这意味着它们仅在须要时获取实际值。但是你须要小心处理他们,否则你可能终极创建了许多微型查询,这会降落数据库性能。
ORM还可以将多个查询批处理到事务中,其操作速率比向数据库发送单个查询快得多。
目前我最喜好的PHP-ORM是Doctrine。我写了一篇关于如何安装Doctrine与CodeIgniter的文章(install Doctrine with CodeIgniter)。
21. 小心利用持久连接
持久连接意味着减少重修连接到MySQL的本钱。 当持久连接被创建时,它将保持打开状态直到脚本完成运行。 由于Apache重用它的子进程,下一次进程运行一个新的脚本时,它将重用相同的MySQL连接。
理论上看起来不错。 但从我个人(和许多其他人)的履历看来,这个功能可能会导致更多麻烦。 你可能会涌现连接数限定问题、内请安题等等。
Apache总是并走运行的,它创建许多子进程。 这是持久连接在这种环境中不能很好事情的紧张缘故原由。 在你考虑利用mysql_pconnect()之前,请咨询你的系统管理员。