目录
笔记大型项目优化概述大型项目优化的方向代码优化数据库优化缓存优化架构优化Memcache与MySQL比较语法参数解释:增/改键(set)获取键值(get)添加键数据(add)修改键数据(replace)删除键(delete)删除所有键(flush_all)递增(incr)和递减(decr)查看当前Memcached运行状态(stats)PHP操作memcacheMemcache的相关算法Redis字符串(string)哈希(Hash)列表(List)集合(Set)有序集合(Sorted Set)键(Key)Mysql优化如何优化MySQL三范式(设计表的规则)设计表:设计表推荐如下字段存储引擎MyIsam和InnoDB存储引擎区别慢查询日志索引MySQL中的执行计划分析查询类型(select_type)分析表名(table)分析额外项(extra)分析连接所使用的类型(type)索引的使用原则(哪些常见情况不能用索引?)前缀索引limit分页优化(百万至千万级快速分页)分表技术为什么需要MySQL分表/分区分区算法分区算法介绍分区语法分区管理SphinxSphinx使用流程安装sphinx配置Sphinx创建索引使用PHP API操作Sphinx匹配模式增量索引(Sphinx索引更新)MongoDB概念什么是NoSQL创建MongoDB服务连接MongoDB服务器入门命令库和集合操作增删改查
笔记
大型项目优化概述
简单理解:读取源码-》词法分析-》创建opcode-》执行opcode重复创建会增加额外的内存和cpu开销
解决方案:安装ZendOptimizer或APC2.0等可以加速PHP代码访问,主要用于缓存opcode而不是每次重复编译减少CPU和内存开销(php5.5+后不需要安装第三方软件,直接开启PHP配置文件中Opcache即可。
大型项目优化的方向
代码优化
开启opcode缓存,减少额外CPU和内存开销,加快代码运行速度
重模型,轻控制器,减少冗余
符合PHP-FIG规范和phpDoc规范,增强代码可读性&可扩展性,有利于团队开发
类: 花括号独占一行
类中方法:华括号独占一行
类名:大驼峰
方法名:小驼峰
命名空间:后面空一行
常量名:大写,多个单词用下划线分割
数据库优化
架构:主从复制、读写分离
设计:存储引擎、字段类型、三范式
功能:缓存、分区、索引
缓存优化
好处:减少数据库查询,将数据缓存到文件或内存中,加快查询数据
实现:
内存(memcache、redis)
文件(使用TP3.2的大S或大F方法,TP5中的Cache类)
内存速度>文件速度>数据库速度
架构优化
负载均衡:将用户请求分配给多个服务器处理(轮询、ip哈希)
集群:多个服务器实现相同的业务
动静分离:将静态资源单独放一台服务器
主从复制:insert/update/delete到主服务器执行,所有从服务器检测大主服务器有写入数据则自动同步
读写分离:通过PHP判断,如果是insert/update/delete交给主服务器处理,如果是select交给从服务器处理
CDN加速:将静态资源缓存到用户所在城市,加快访问速度
Memcache
概念:一个数据库,但是数据存在内存中
作用:常用来做缓存服务器、将从数据库查询的数据缓存起来,减少数据库查询、加快查询速度
数据存储在内存中系统重启则丢失
与MySQL比较
共同点:都是C/S架构
不同点:MySQL存磁盘文件、memcache存在内存中
不同点:MySQL存储数据要先创建数据库再创建表、memcache直接以键值对形式存储
键key值value
字符串(唯一)字符串、整数、浮点数、布尔、数组、对象、NULL、二进制数据(图片、视频、音频)
语法参数解释:
键 - 最大长度不超过250字符
是否压缩 - 1-是,0-否(以空间换时间)
缓存时间 - 0-理论永久,其他-单位秒(注:最大存储时间30天)
数据长度 - 写数字,单位字节(注:回车输入具体内容)
增/改键(set)
语法:set 键 是否压缩 缓存时间 数据长度
说明: 键存在-则修改,键不存在-则创建
获取键值(get)
语法:get 键
添加键数据(add)
语法:add 键 是否压缩 缓存时间/s 数据长度/字节�
说明:只能添加不能修改
修改键数据(replace)
语法:replace 键 是否压缩 缓存时间/s 数据长度/字节
说明:只能修改不能添加
删除键(delete)
语法:delete 键
删除所有键(flush_all)
语法:flush_all
递增(incr)和递减(decr)
语法:incr 键 数字
语法:decr 键 数字
说明:返回增长后的结果,键必须存在
查看当前Memcached运行状态(stats)
pid: memcache服务器进程ID
uptime:服务器已运行秒数
time:服务器当前Unix时间戳
version:memcache版本
pointer_size:操作系统指针大小
rusage_user:进程累计用户时间
rusage_system:进程累计系统时间
curr_connections:当前连接数量
total_connections:Memcached运行以来连接总数
connection_structures:Memcached分配的连接结构数量
cmd_get:get命令请求次数
cmd_set:set命令请求次数
cmd_flush:flush命令请求次数
get_hits:get命令命中次数
get_misses:get命令未命中次数
delete_misses:delete命令未命中次数
delete_hits:delete命令命中次数
incr_misses:incr命令未命中次数
incr_hits:incr命令命中次数
decr_misses:decr命令未命中次数
decr_hits:decr命令命中次数
cas_misses:cas命令未命中次数
cas_hits:cas命令命中次数
cas_badval:使用擦拭次数
auth_cmds:认证命令处理的次数
auth_errors:认证失败数目
bytes_read:读取总字节数
bytes_written:发送总字节数
limit_maxbytes:分配的内存总大小(字节)
accepting_conns:服务器是否达到过最大连接(0/1)
listen_disabled_num:失效的监听数
threads:当前线程数
conn_yields:连接操作主动放弃数目
bytes:当前存储占用的字节数
curr_items:当前存储的数据总数
total_items:启动以来存储的数据总数(包括过期的)
evictions:LRU释放的对象数目
reclaimed:已过期的数据条目来存储新数据的数目
PHP操作memcache
先开启memcache扩展即可
语法:
创建mem对象:$mem = new Memcache;
连接服务器: $mem->connect(服务ip地址,端口)
关闭服务器: $mem->close();
设置数据: $mem->set(键,值 [,是否压缩,缓存时间])
获取数据: $mem->get(键)
递增: $mem->incrment(键,数字);递减: $mem->decrment(键,数字);
Memcache的相关算法
惰性过期机制
说明:memcached内部不会监视记录是否过期,而是在get时查看记录的时间戳,检查记录是否过期。这种技术被称为惰性过期
好处:减少监控过期产生的开销
最近最少使用算法
缓存空间已满,采用LRU策略,将使用频率最低数据进行删除
Redis
字符串(string)
设置1个键: set 键 值
设置n个键:mset 键1 值1 .. 键n 值n
获取1个键: get 键
获取n个键:mget 键1 键n
递增递减: incr/decr 键
增减指定: incrby/decrby 键 数字
追加: append 键 内容
截取: substr 键 起始位置 结束位置(注:下标从0开始,含前含后)
哈希(Hash)
设置1个值: hset 键 字段 值
获取1个值: hget 键 字段
设置n个值:hmset 键 字段1 值1 ... 字段n 值n
获取n个值:hmget 键 字段1 ... 字段n
检测字段: hexists 键 字段
删除字段: hdel 键 字段
字段个数: hlen 键
所有字段: hkeys 键
所有值: hvals 键
所有字段值:hgetall 键
列表(List)
压入:lpush/rpush 键 值
弹出:lpop/rpop 键
查询:lrange 键 起始位置 结束位置
集合(Set)
添加:sadd 集合名 数据
删除:srem 集合名 数据
查看:smembers 集合名
差集:sdiff 集合名1 ... 集合名n 我有你没有
交集:sinter 集合名1 ... 集合名n 大家都有的
并集:sunion 集合名1 ... 集合名n 合并去重
有序集合(Sorted Set)
添加:zadd 集合名 数据 成员
删除:zrem 集合名 成员
查看: zrange 集合名 起始位置 结束位置 [withscores] (升序)
查看: zrevrange 集合名 起始位置 结束位置 [withscores] (降序)
键(Key)
键是否存在:exists 键
键类型: type 键
键查询: keys *
键更名: rename 旧键 新键
键统计: dbsize
键设置过期:expire 键 秒数
查看过期: ttl 键 (明确:过期则代表不存在,不存在-2,未设置-1)
选择数据库:select 下标(注:通过redis.conf声明数据库个数)
删除当前库:flushdb
删除所有库:flushall
Mysql优化
如何优化MySQL
架构:主从复制、读写分离
设计:三范式+逆范式、存储引擎、列类型的选择
功能:索引、缓存、分区
三范式(设计表的规则)设计表:
确保每列/字段保持原子性
有主键,且非主键字段依赖主键
消除传递依赖,非主键字段不能相互依赖
好处:减少冗余,提高表的查询速度
逆范式:用空间换时间
设计表推荐如下字段
编号、创建于、更新于、是否删除
存储引擎
名词,指MySQL按照指定数据格式存储
myisam:速度快,但不支持事务和外键约束
innodb:支持事务,行级锁定,外键约束
archive:只可插入和查询,不支持删除和修改
memory:存储在内存,了解
MyIsam和InnoDB存储引擎区别
存储结构:myisam - 3个文件、innodb - 2个文件
锁:myisam - 仅支持表锁,innodb - 行锁&表锁
事物和外键支持:myisam - 不支持 , innodb -支持
CURD操作:
myisam:大量查询
innodb:大量的插入和修改
全文检索:仅MySQL5.6以下innodb不支持(都不支持中文)
慢查询日志
作用:为了防止sql出问题,查询过慢。
方法:通过MySQL记录执行较长的SQL语言
使用如下指令查看慢查询日志是否开启
showvariableslike'%slow_query%'
没开启,就手工开启慢查询日志
setglobalslow_query_log =1;
设置查询的临界时间(查询超过指定时间后纪录)
showvariableslike'%query_time%';
setgloballong_query_time =2;
使用查询语句(超时)
insertintophp_slow_log2values('zzzzzz','zzzzzz');
insertintophp_slow_log2(name,name2)selectname,name2fromphp_slow_log2;
验证记录慢SQL语句,查看日志的记录
索引
四种索引形式:
普通索引(index) - 仅仅为了提高查询速度
唯一索引(unique) - 保存数据唯一性不能重复
主键索引(primary key) - 既保存数据唯一又不能为null 编号
全文检索(fulltext) - 提取关键字添加索引(明天详细说) like
组合索引(index) - 给多个字段添加相同的索引
新建表时添加索引:
修改表时添加索引或者删除索引
修改表添加索引:alter table 表名 add 索引类型 索引名(字段)
删除表指定索引:drop index 索引名 on 表名
MySQL中的执行计划
就是通过explain语法分析SQL语句
语法:explain SQL语句 \G
说明:\G后面不要加分号
字段类型含义
select_type查询类型
table表名
type连接类型
possible_keys可能用到的索引
key实际用到索引
key_len索引长度
rows检索了多少数据,最终显示结果
分析查询类型(select_type)
simple:不含子查询
primary:含子查询或派生查询
subquery :非from子查询
derived:from型子查询
union
union result
分析表名(table)
实际表名
表别名
derived(from型子查询)
null
分析额外项(extra)
index:是指用到了索引覆盖,效率非常高
using where:是指光靠索引定位不了,还得where判断一下
extra中出现以下2项意味着MySQL根本不能使用索引,效率会受到重大影响,应尽可能对此进行优化
using temporary:表示 MySQL 在对查询结果排序时使用临时表。常见于排序 order by 和分组查询 group by
using filesort:表示 MySQL 会对结果使用一个外部索引排序,而不是从表里按索引次序读到相关内容。可能在内存或者磁盘上进行排序。MySQL 中无法利用索引完成的排序操作称为“文件排序”
分析连接所使用的类型(type)
最好的是 system 一般在表中只有一行记录的或者查询系统表的时候出现。
其次就是 const 一般在使用主键索引的时候会出现。
其其次 range 一般在做范围查询的时候会使用 id < 100。
index 代表可以使用索引做一些优化,一般在查询表的总行数的时候出现。
all 一般使用不上索引的时候出现。
. ref 意思是指 通过索引列,可以直接引用到某些数据行. eq_ref 意思是指 通过索引列,可以直接引用某1行数据
索引的使用原则(哪些常见情况不能用索引?)
说明:
like查询(“%”和“_”开头)索引失效
or运算都要具有索引,否则索引失效
where条件字段是字符串类型必须加引号
组合索引字段单独使用,左边生效,右边失效(左原则)
前缀索引
概念:就是给字段内容前n个字符添加索引(前n个字符必须具备唯一性)
好处:加快查询速度
语法:
altertable表名add索引类型 索引名(字段(字符))
limit分页优化(百万至千万级快速分页)
由于数据量大超过一定页后SQL语句查询慢
问题分析:如果只想查询最后的5条数据,但是一般查询限制会查询所有数据,所以效率极低
解决方法:
从业务角度(百度、谷歌),限制页面展示的数量
从索引角度
以前是通过SQL语句限制数据,会过滤全部数据
通过id或者其它条件过滤,避免不必要的性能影响
分表技术
水平分表
当一个表很大时我们创建索引后,查询速度还是很慢,把一个大表按照某个标准分割成小表,这样可以提高查询的速度
(用户ID)%(表个数),再通过取余出来的结果排序
垂直分表
一个表有很多字段,查询慢。可以通过区分常用字段和不常用字段
为什么需要MySQL分表/分区
水平分表或分区,都是为了加快查询速度
水平分表需要手动在应用层写逻辑代码,但是通过分区可以避免,由MySQL底层实现,我们只需要写原生SQL语句
分区算法
分区算法介绍
求余(主键字段):key求余算法、hash算法
条件:list-数据必须在指定集合中,range-数据在执行范围中
分区语法
createtable表名名(
)engine=存储引擎charset=编号
partitionby算法名(字段)partitions数字;
分区管理
取余管理:增加分区-不影响原数据,删除分区-不影响原数据
条件管理:增加分区-不影响原数据,删除分区-数据丢失
取余管理(key,hash)
增加分区数量:alter table 表名 add partition partitions 数字
减小分区数量:alter table 表名 coalesce partition 数字
条件管理(list,range)
删除分区:alter table 表名 drop partition 分区名
添加分区:
Sphinx
一个软件,用来代替MySQL全文检索
特性:(强、快)
高速的建立索引(峰值性能能达10M/s)
高性能的搜索(在2-4G的文本数据上,平均每次检索时间小于0.1秒)
可处理海量数据
优势
Sphinx单一索引最大可包含1亿条记录,在1千万条记录情况下的查询速度为0.x秒(毫秒级)
Sphinx创建索引的速度为:创建100万条记录的索引只需3~4分钟,创建1000万条记录的索引可以在50分钟内完成,而只包含最新10万条记录的增量索引,重建一次只需几十秒
Sphinx使用流程
通过sphinx去MySQL中获取并建立索引文件
通过php去sphinx中查询数据并返回ID
根据ID去MySQL中查询具体数据
安装sphinx
配置Sphinx
创建数据库
将etc/csft_mysql.conf复制并更名为sphinx.conf
复制下面代码替换shpinx.conf中的内容(红色-可能需要修改,绿色-存在对应关系)
#数据源:数据来源定义(数据库信息、数据源SQL语句)
source music
{
#下面是sql数据库特有的端口,用户名,密码,数据库名等。
type = mysql
sql_host = localhost
sql_user = root
sql_pass = admin
sql_db = youhua3
sql_port = 3306
sql_query_pre = SET NAMES utf8
#sql_query属性:取出要创建索引的数据
#要求1:SELECT的第一个字段必须是主键、
#要求2:第一个字段的名字(别名)必须是id
#要求3:其他的字段就是要创建索引的字段
#需 求:为歌曲表中的title和author和content字段创建索引
sql_query = SELECT id, title, author, content FROM music
}
#索引的定义(索引文件存放的位置,索引文件的名字)
#每个index对应一个数据源,用来定义这个数据源生成的索引文件的信息
index music
{
#该索引对应哪个数据源
source = music
#索引文件存放的目录和名字(存到E:/sphinx/var/data/目录下,索引文件的名字是music)
path = E:/sphinx/var/data/music
docinfo = extern
mlock = 0
morphology = none
min_word_len = 1
html_strip = 0
#词库文件所在的目录
charset_dictpath = E:/sphinx/etc/
#字符集编码类型,可以为:(sbcs,utf-8,zh_cn.utf-8,zh_ch.gbk,zh_ch.big5)
charset_type = zh_cn.utf-8
}
#全局index定义
indexer
{
#建立索引的时候,索引内存限制
mem_limit = 128M
}
#searchd服务定义
searchd
{
listen = 9312
read_timeout = 5
max_children = 30
max_matches = 1000
seamless_rotate = 0
preopen_indexes = 0
unlink_old = 1
# 进程id文件
pid_file = E:/sphinx/var/log/searchd_mysql.pid
# 系统日志存放的位置
log = E:/sphinx/var/log/searchd_mysql.log
# 查询日志存放的位置
query_log = E:/sphinx/var/log/query_mysql.log
}
index music 创建music索引(和source一一对应,表示该索引通过哪些数据创建)
source music1 创建music数据源
创建索引
创建指定索引语法:indexer.exe -c 配置文件 索引名
创建全部索引语法:indexer.exe -c 配置文件 --all
使用PHP API操作Sphinx
创建服务:bin\searchd.exe -c 配置文件 --install
删除服务:sc delete 服务名
启动服务:net start 服务名
关闭服务:net stop 服务名
匹配模式
$sp->SetMatchMode(常量)
常量规则
SPH_MATCH_ALL 匹配所有词(默认)SPH_MATCH_ANY 匹配一个词
SPH_MATCH_PHRASE 匹配整一个词
SPH_MATCH_BOOLEAN 将查询看作一个布尔表达式
SPH_MATCH_EXTENDED 查询看做一个sphinx的表达式
将sphinx的结果转化为具体的信息
通过sphinx去mysql中获取数据并建立索引文件
通过php去sphinx匹配数据ID
根据ID去数据库中查询数据
增量索引(Sphinx索引更新)
概念:更新sphinx索引文件的表现称之为增量索引
语法:
创建索引语法:indexer -c 配置文件 索引名
合并索引语法:indexer -c 配置文件 --merge 主索引名 新索引名 --rotate
MongoDB