PHP数据库编程之MySQL优化策略概述

发布时间 - 2026-01-11 02:49:14    点击率:

本文简单讲述了PHP数据库编程之MySQL优化策略。分享给大家供大家参考,具体如下:

前些天看到一篇文章说到PHP的瓶颈很多情况下不在PHP自身,而在于数据库。我们都知道,PHP开发中,数据的增删改查是核心。为了提升PHP的运行效率,程序员不光需要写出逻辑清晰,效率很高的代码,还要能对query语句进行优化。虽然我们对数据库的读取写入速度上却是无能为力,但在一些数据库类扩展像memcache、mongodb、redis这样的数据存储服务器的帮助下,PHP也能达到更快的存取速度,所以了解学习这些扩展也是非常必要,这一篇先说一下MySQL常见的优化策略。

几条MySQL小技巧

1、SQL语句中的关键词最好用大写来书写,第一易于区分关键词和操作对象,第二,SQL语句在执行时,MySQL会将其转换为大写,手动写大写能增加查询效率(虽然很小)。
2、如果我们们经对数据库中的数据行进行增删,那么会出现数据ID过大的情况,用ALTER TABLE tablename AUTO_INCREMENT=N,使自增ID从N开始计数。
3、对int类型添加 ZEROFILL 属性可以对数据进行自动补0
4、导入大量数据时最好先删除索引再插入数据,再加入索引,不然,mysql会花费大量时间在更新索引上。
5、创建数据库书写sql语句时 ,我们可以在IDE里创建一个后缀为.sql的文件,IDE会识别sql语法,更易于书写。更重要的是,如果你的数据库丢失了,你还可以找到这个文件,在当前目录下使用/path/mysql -uusername -ppassword databasename < filename.sql来执行整个文件的sql语句(注意-u和-p后紧跟用户名密码,无空格)。

数据库设计方面优化

1、数据库设计符合第三范式,为了查询方便可以有一定的数据冗余。

2、选择数据类型优先级 int > date,time > enum,char>varchar > blob,选择数据类型时,可以考虑替换,如ip地址可以用ip2long()函数转换为unsign int型来进行存储。

3、对于char(n)类型,在数据完整的情况下尽量较小的的n值。

4、在建表时用partition命令对单个表分区可以大大提升查询效率,MySQL支持RANGE,LIST,HASH,KEY分区类型,其中以RANGE最为常用,分区方式为:

CREATE TABLE tablename{
}ENGINE innodb/myisam CHARSET utf8 //选择数据库引擎和编码
PARTITION BY RANGE/LIST(column),//按范围和预定义列表进行分区
PARTITION partname VALUES LESS THAN /IN(n),//命名分区并详细限定分区的范围

5、选择数据库引擎时要注意innodb 和 myisam的区别

存储结构:MyISAM在磁盘上存储成三个文件。而InnoDB所有的表都保存在同一个数据文件中,一般为2GB
事务支持:MyISAM不提供事务支持。InnoDB提供事务支持事务。
表锁差异:MyISAM只支持表级锁。InnoDB支持事务和行级锁。
全文索引:MyISAM支持 FULLTEXT类型的全文索引(不适用中文,所以要用sphinx全文索引引擎)。InnoDB不支持。
表的具体行数:MyISAM保存有表的总行数,查询count(*)很快。InnoDB没有保存表的总行数,需要重新计算。
外键:MyISAM不支持。InnoDB支持

索引方面优化

1、innodb是聚簇索引,存储索引时必须有主键,如果没有指定,引擎会自动生成一个隐藏的主键,生成一个主索引,索引内存放的是主键的物理地址,数据靠主键存放,每次使用索引时要先找到主索引,然后找到主索引下的数据。

优点通过主键查找特别快,缺点是次级索引会变慢,因为需要先通过次级索引(次级索引里是主索引的位置。)找到主索引,然后通过主索引找数据。并且如果主键无规律,插入新值时需要移动较多数据块,会影响效率,所以要尽量使用有规律递增的int型做主键。还有因为数据紧跟着主键放,所以如果数据中有数据量特别大的列(text/blob),innodb查询时会跳过很多数据块,也会导致慢。

2、myisam的索引各个索引都相同统一指向磁盘上各个行的地址,都是轻量级的指针数据。缺点是各个索引的建立不是通过主键,查询没有聚簇索引查找主键快。但其因为存储的是地址,所以在插入新值时比较方面移动改变。

3、进行多条件查询时,对多条件分别建立索引时,执行sql查询时,MySQL只会选择一个最贴近的索引来使用,所以如果需要多条件查询,要建立联合索引,即使会造成数据冗余。

联合索引的BTREE建立方法:对第一个条件建立索引,在第一个索引的BTREE区域对第二个条件建立索引,以此类推,所以,在使用索引时,不用第一个条件用第二个条件也不会用到联合索引。使用索引时要条件要有顺序,有序列的使用。

4、索引长度对查询也有很大影响,我们应该尽量建立短的索引长度,我们可以使用查询列

SELECT COUNT(DISTINCT LEFT(column)) / COUNT(*) FROM tablename  来测试对column列建立索引时选取不同的长度,索引的覆盖率有多大,我们选择一下接近饱和的n个长度来建立索引
ALTER TABLE tablename ADD INDEX (column(n));  来对某一列的前n个字符建立索引。若前n个字符相同,我们甚至可以对字符串进行反转存储,然后建立索引。

5、对于经常修改导致的索引碎片的维护方式:ALTER TABLE tablename ENGINE oldengine;即再次应用一下表存储引擎,使其自动维护;也可以用 OPTIMIZE tablename 命令来进行维护。

数据查询方面优化

数据库操作尽量少查询,有查询时尽量不在数据库层面上进行数据操作,而是返回到PHP脚本中操作数据,减轻数据库压力。

一旦发现有数据库性能问题,要及时解决,一般用慢查询日志记录查询很"慢"的语句,用EXPLAIN分析查询和索引使用情况,用PROFILE分析语句执行时的具体资源消耗。

慢查询日志:

1、在my.ini或my.cnf的[mysqld]下添加

slow_query_log_file=/path //设置日志存储路径
long_query_time=n //设置如果语句执行时间达到n秒,就会被记录下来

2、然后在MySQL里设置SET slow_query_log='ON'来开启慢查询。

3、记录下日志后,我们用/bin/目录下的mysqldumpslow filename来查看日志,其常用参数如下:

-g pattern 使用正则表达式
-t n返回前n条数据
-s c/t/l/r 以记录次数/时间/查询时间/返回记录数来排序

EXPLAIN语句

使用方法,在要执行的查询语句前面加EXPLAIN

EXPLAIN SELECT * FROM user;

得到形如下图的结果:

下面是对每一项的解释:

id 查询语句的id,简单查询无意义,多重查询时可以看出执行查询的顺序
select-type 执行的查询语句的类型,对应多重查询,有simple/primary/union等。
tabel 查询语句查询的数据表
type  获得数据的类型 常见的类型效率从高到低为 null>const>eq_ref>ref>range>index>all
possible-keys:可能使用到的索引
key 使用到的索引
key_len索引长度
ref 使用哪个列与索引一起从表中选择。
rows  查找到数据要扫描的大概行数,可看出索引的优劣
extra  常见的有
using filesort 查询到数据后进行文件排序,较慢,需要优化索引
using where 读取整行数据后进行判断过滤,是否符合where条件
using index 索引覆盖,即在牵引中已经有这存储了目标数据,直接读取索引,很快。

PROFILE

用SELECT @@frofiling来查看PROFILE的开启状态。
如果未开启,用SET profiling=1来开启。
开启之后,再执行查询语句,MySQL会自动记录profile信息。
应用show profiles查看所有的sql信息,结果为 Query_ID Duration Query三列结果,分别是查询ID,用时和所用的sql语句。
我们可以使用

SHOW PFROFILE [type[,type]][FOR QUREY Query_ID][Limit rwo_count [OFFSET offset]]

type常见有ALL(全部) BLOCK IO(显示IO相关开销) CPU(CPU开销) MEMORY(内存开销)等

大型存储方面优化

数据库主从复制和读写分离

1、master将改变记录到二进制日志中,slave将master的二进制拷贝到它的中继日志中,重新将数据返回到它自己的数据中,达到复制主服务器数据的目的。

主从复制可以用作:数据库负载均衡、数据库备份、读写分离等功能。

2、配置主服务器master

修改my.ini/my.conf

[mysqld]
log-bin=mysql-bin //启用二进制日志
server-id=102 //服务器唯一ID

3、配置从服务器slave

log-bin=mysql-bin //启用二进制日志
server-id=226 //服务器唯一ID

4、在主服务器上授权从服务器

GRANT REPLICATION SLAVE ON *.* to 'slavename'@'IP' identified by 'root'

5、在从服务器上使用

change master to
master_host="masterip",
master_user="masteruser",
master_password="masterpasswd";

6、然后使用start slave命令开始进行主从复制。

不要忘记在每次修改配置后重启服务器,然后可以在主从服务器上用show master/slave status查看主/从状态。

实现数据库的读写分离要依赖MySQL的中间件,如mysql_proxy,atlas等。通过配置这些中间件来对主从服务器进行读写分离,使从服务器承担被读取的责任,从而减轻主服务器的负担。

数据库的sharding

在数据库中数据表中的数据量非常庞大的时候,无论是索引还是缓存等压力都很大,对数据库进行sharding,使之分别以多个数据库服务器或多个表存储,以减轻查询压力。

方式有垂直切分、水平切分和联合切分。

垂直切分:在数据表非常多的时候,把数据库中关系紧密(如同一模块,经常连接查询)的表切分出来分别放到不同的主从server上。

水平切分:在表不多,而表里的数据量非常大的时候,为了加快查询,可以用哈希等算法,将一个数据表分为几个,分别放到不同的服务器上,加快查询。水平切分和数据表分区的区别在于其存储介质上的不同。

联合切分:更多的情况是数据表和表中的数据量都非常大,则要进行联合切分,即同时进行垂直和水平分表,将数据库切分为一个分布式的矩阵来存储。

这些数据库的优化方式,每一种拿出来都可以写作一篇文章,可谓是博大精深,了解并记忆了这些方式,可以在有需要的时候进行有目的的选择优化,达到数据库效率的高效。

接下来我们会进一步总结一下常用的PHP数据库类扩展memcache、redis和mongodb的基本使用场景和使用方式。

更多关于PHP相关内容感兴趣的读者可查看本站专题:《php+mysql数据库操作入门教程》、《php+mysqli数据库程序设计技巧总结》、《php面向对象程序设计入门教程》、《PHP数组(Array)操作技巧大全》、《php字符串(string)用法总结》及《php常见数据库操作技巧汇总》

希望本文所述对大家PHP程序设计有所帮助。


# PHP  # MySQL  # 优化  # PHP执行批量mysql语句的解决方法  # 使用phpMyAdmin批量修改Mysql数据表前缀的方法  # php+mysqli实现批量执行插入、更新及删除数据的方法  # php+mysqli批量查询多张表数据的方法  # php往mysql中批量插入数据实例教程  # PHP mysqli 增强 批量执行sql 语句的实现代码  # php从memcache读取数据再批量写入mysql的方法  # php+mysqli实现批量替换数据库表前缀的方法  # php中批量删除Mysql中相同前缀的数据表的代码  # PHP实现mysqli批量执行多条语句的方法示例  # php+mysql查询优化简单实例  # PHP优化之批量操作MySQL实例分析  # 关键词  # 切分  # 主键  # 的是  # 第一个  # 行数  # 可以用  # 器上  # 时要  # 数据库中  # 多条  # 程序设计  # 多个  # 第二个  # 不支持  # 可以使用  # 转换为  # 非常大  # 一篇文章  # 自己的 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Win11任务栏卡死怎么办 Windows11任务栏无反应解决方法【教程】  如何使用 jQuery 正确渲染 Instagram 风格的标签列表  如何批量查询域名的建站时间记录?  如何快速搭建高效简练网站?  lovemo网页版地址 lovemo官网手机登录  javascript中闭包概念与用法深入理解  Laravel Fortify是什么,和Jetstream有什么关系  Laravel项目结构怎么组织_大型Laravel应用的最佳目录结构实践  详解Nginx + Tomcat 反向代理 负载均衡 集群 部署指南  如何在新浪SAE免费搭建个人博客?  javascript中的数组方法有哪些_如何利用数组方法简化数据处理  详解CentOS6.5 安装 MySQL5.1.71的方法  canvas 画布在主流浏览器中的尺寸限制详细介绍  Laravel事件监听器怎么写_Laravel Event和Listener使用教程  Laravel如何保护应用免受CSRF攻击?(原理和示例)  JavaScript如何实现倒计时_时间函数如何精确控制  如何用好域名打造高点击率的自主建站?  Laravel如何实现API速率限制?(Rate Limiting教程)  如何用西部建站助手快速创建专业网站?  如何在腾讯云服务器上快速搭建个人网站?  Laravel项目怎么部署到Linux_Laravel Nginx配置详解  Python文本处理实践_日志清洗解析【指导】  高配服务器限时抢购:企业级配置与回收服务一站式优惠方案  Midjourney怎么调整光影效果_Midjourney光影调整方法【指南】  ,怎么在广州志愿者网站注册?  Mybatis 中的insertOrUpdate操作  android nfc常用标签读取总结  HTML透明颜色代码怎么让下拉菜单透明_下拉菜单透明背景指南【技巧】  Laravel如何实现多级无限分类_Laravel递归模型关联与树状数据输出【方法】  EditPlus中的正则表达式 实战(1)  Laravel队列任务超时怎么办_Laravel Queue Timeout设置详解  Laravel如何生成URL和重定向?(路由助手函数)  Laravel如何使用Eloquent ORM进行数据库操作?(CRUD示例)  网站制作公司哪里好做,成都网站制作公司哪家做得比较好,更正规?  消息称 OpenAI 正研发的神秘硬件设备或为智能笔,富士康代工  如何在自有机房高效搭建专业网站?  网站视频制作书签怎么做,ie浏览器怎么将网站固定在书签工具栏?  DeepSeek是免费使用的吗 DeepSeek收费模式与Pro版本功能详解  如何快速上传建站程序避免常见错误?  如何用免费手机建站系统零基础打造专业网站?  如何在万网利用已有域名快速建站?  Laravel如何实现密码重置功能_Laravel密码找回与重置流程  制作公司内部网站有哪些,内网如何建网站?  Laravel Eloquent关联是什么_Laravel模型一对一与一对多关系精讲  js代码实现下拉菜单【推荐】  香港服务器如何优化才能显著提升网站加载速度?  Laravel storage目录权限问题_Laravel文件写入权限设置  WEB开发之注册页面验证码倒计时代码的实现  详解Android——蓝牙技术 带你实现终端间数据传输  海南网站制作公司有哪些,海口网是哪家的?