PHP重点知识复习 – MySQL索引的基础和类型

一、MySQL索引的基础和类型

1.索引的基础

索引类似于书籍的目录,要想找到一本书的某个特定主题,需要先查找书的目录,定位对应的页码。

存储引擎使用类似的方式进行数据查询,先去索引当中找到对应的值,然后根据匹配的索引找到对应的数据行。

2.索引对性能的影响

优点:

大大减少服务器需要扫描的数据量

帮助服务器避免排序和临时表

将随机I/O变成顺序I/O

大大提高查询的速度

缺点:

降低写的速度、占用磁盘

3.索引的使用场景

对于非常小的表,大部分情况下全表扫描效率更高

中到大型表,索引非常有效

特大型的表,建立和使用索引的代价将随之增长,可以使用分区技术来解决

4.索引的类型

索引有很多中类型,都是实现在存储引擎层的

普通索引:最基本的索引,没有任何约束限制

唯一索引:与普通索引类似,但是具有唯一性约束

主键索引:特殊的唯一索引,不允许有空值

一个表只能有一个主键索引,可以有多个唯一索引

主键索引一定是唯一索引,唯一索引不是主键索引

主键可以与外键构成参照完整性约束,防止数据不一致

组合索引(复合索引):将多个列组合在一起创建索引,可以覆盖多个列

外键索引:只有InnoDB类型的表才可以使用外键索引,保证数据的一致性、完整性和实现级联操作

全文索引:MySQL自带的全文索引只能用于MyISAM,并且只能对英文进行全文索引

外键索引和全文索引不常用,一般外键索引的功能我们可以在程序逻辑中实现,全文索引可以使用ES等全文搜索引擎实现。

二、MySQL索引的创建原则

原则

1.最适合索引的列是出现在WHERE子句中的列,或连接字句中的列而不是出现在SELECT关键字后的列

比如 select id,email,tel from user where username = “xiaofan”;  这里我们应该选择 username 作为索引

2.索引列的基数越大,索引的效果越好

3.对字符串进行索引,应该制定一个前缀长度,可以节省大量的索引空间,这个就被称为前缀索引

比如,下面username长度比较长,如果创建完整的索引值,会影响索引效率。我们可以选择合适长度的前缀作为索引。下面选择username前5个字符作为索引

create table user(
  `id` int unsigned not null auto_increament primary key,
  `username` varchar(32) not null default '',
  KEY user_username(username(5))
);

4.根据情况创建复合索引,复合索引可以提交查询效率

比如,我们查找一本书的某一章下面的某一节内容,使用复合索引会大大提高查询效率

create table user(
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `username` VARCHAR(32) NOT NULL DEFAULT '',
  `password` CHAR(32) NOT NULL DEFAULT '',
  UNIQUE user_username_password(`username`,`password`)
);

也可以使用 KEY user_username_password(username,password),但是由于上面的表中用户名和密码是有唯一关联性的所以用UNIQUE更合适,效率更高。

5.避免创建过多索引,索引会额外占用磁盘空间,降低写操作效率

6.主键尽可能选择较短的数据类型,可以有效减少索引的磁盘占用提高查询效率

三、MySQL索引的注意事项

注意

1.复合索引遵循前缀原则

比如

KEY(a,b,c)

WHERE a = 1 and b = 2 and c = 3

WHERE  a = 1 and b =2

WHERE a = 1

以上查询语句可以使用到定义的复合索引

WHERE b = 2 and c =3

WHERE a = 1 and c =3

以上这两个就是无法使用到复合索引

因为复合索引遵循前缀原则,只能从左到右依次查询

2.like查询,%不能在前,可以使用全文索引

比如

index user_username(username)

where name like “wang%” 这样可以使用索引

where name like “%wang%” 这样就不能使用索引了

3.column is null 可以使用索引

4.如果MySQL估计使用索引比全表扫描更慢,会放弃使用索引

5.如果 or 关键字前的条件中的列有索引,后面的没有,索引都不会被用到

6.列类型是字符串,查询时一定要给值加引号,否则索引失效

比如

name varchar(20)

where name = 100;  //这里可能有个name值是100,查询时不带引号,索引会失效

正确写法是 where name = “100”.

 

PHP重点知识复习 – MySQL数据库基础

一、MySQL数据类型

1.整数类型

TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT

属性:UNSIGNED

2.实数类型

FLOAT、DOUBLE、DECIMAL

DECIMAL存储比BIGINT更大的整数,可以存储精确的小数

FLOAT和DOUBLE类型支持使用标准的浮点进行近似计算

3.字符串类型

VARCHAR、CHAR、TEXT、BLOB

VARCHAR类型用于存储可变长度的字符串,它比CHAR定长类型更节省空间

VARCHAR类型会使用1或2个额外字节记录字符串的长度,列长度小于255个字节,使用1个字节表示,否则用2个

CHAR是定长的,根据定义的字符串长度分配足够的空间

CHAR会根据需要采用空格填充以方便比较

CHAR适合存储很短的字符串,或者所有值都接近同一长度

超出CHAR定义的长度,字符串会被截断

对于经常变更的数据,CHAR比VARCHAR更好,CHAR不易产生碎片

对于非常短的列,CHAR比VARCHAR在存储空间上更有效率

只分配真正需要的空间,更长的列会消耗更多的内存

尽量避免使用BLOB或TEXT,查询会使用临时表,导致严重的性能开销。

4.枚举类型

有时可以使用枚举代替常用的字符串类型

把不重复的集合存储成一个预定义的集合

非常紧凑,把列表值压缩到一个或两个字节

内存存储的是整数

尽量避免使用数字作为ENUM枚举的常量,易混乱

排序是按照内部存储的整数进行排序

枚举表会使表大小大大减小

5.日期和时间类型

尽量使用TIMESTAMP,比DATETIME空间效率高

用整数保存时间戳的格式通常不方便处理

如果需要存储微秒,可以使用BIGINT存储

6.列属性

auto_increment、default、not null、zerofill

二、MySQL数据表引擎

InnoDB表引擎

默认事务型引擎,最重要最广泛的存储引擎,性能非常优秀

数据存储在共享表空间,可以通过配置分开

对主键查询的性能高于其他类型的存储引擎

内部做了很多优化,从磁盘读取数据时自动在内存构建hash索引,插入数据时自动构建插入缓冲区

通过一些机制和工具支持真正的热备份

支持崩溃后的安全恢复

支持行级锁

支持外键

MyISAM表引擎

5.1版本前,MyISAM是默认的存储引擎

拥有全文索引、压缩、空间函数

不支持事务和行级锁,不支持崩溃后的安全恢复

表存储在两个文件,MYD和MYI

设计简单,某些场景下性能很好

其他表引擎

Archive、Blackhole、CSV、Memory

优先选择InnoDB

三、MySQL锁机制

1.基础概念

当多个查询同一时刻进行数据修改时,就会产生并发控制的问题

共享锁和排他锁,其实就是读锁和写锁

2.读锁

共享的,不堵塞,多个用户可以同时读一个资源,互不干扰

3.写锁

排他的,一个写锁会阻塞其他的写锁和读锁,这样可以只允许一个人进行写入,防止其他用户读取正在写入的资源。

4.锁粒度

表锁,系统性能开销最小,会锁定整张表,MyISAM使用表锁

行锁,最大程度地支持并发处理,但是也带来了最大的锁开销,InnoDB使用行级锁

四、MySQL事务处理

1.事务处理

MySQL提供事务处理的表引擎,InnoDB

服务器层不管理事务,由下层的引擎实现,所以同一个事务中,使用多种存储引擎不靠谱(也就是多张表需要都使用InnoDB引擎,才能进行正常的事务处理)

在非事务的表上执行事务操作MySQL不会发出提醒,也不会报错

因此,在进行事务处理时,需要首先检查下表是否使用的InnoDB引擎

2.存储过程

为以后的使用而保存的一条或多条MySQL语句的集合

存储过程就是有业务逻辑和流程的集合

可以在存储过程中创建表,更新数据,删除等等

3.使用场景

通过把处理封装在容易使用的单元中,简化复杂的操作

保证数据的一致性

简化对变动的管理

五、MySQL触发器

1.触发器

提供给程序员和数据分析员来保证数据完整性的一种方法,它时与表事件相关的特殊的存储过程

2.使用场景

可以通过数据库中的相关表实现级联更改

实时监控某张表中的某个字段的更改而需要做出相应的处理

某些业务编号的生成等

滥用会造成数据库及应用程序的维护困难

 

此部分内容还可以参考 《MySQL数据库》

PHP重点知识复习 – Linux基础(待完善)

一、linux常用命令

1.进程管理

w、top、ps、kill、pkill、pstree、killall

2.用户管理

id、usermod、useradd、groupadd、userdel

3.文件系统

mount、umount、fsck、df、du

4.系统关机和重启

shutdown、reboot

5.网络应用

curl、telnet、mail、elinks

6.网络测试

ping、netstat、host

7.网络配置

hostname、ifconfig

8.常用工具

ssh、screen、clear、who、date

9.软件包管理

yum、rpm、apt-get

10.文件查找和比较

locate、find

11.文件内容查看

head、tail、less、more

12.文件处理

touch、unlink、rename、In、cat

13.目录操作

cd、mv、rm、pwd、tree、cp、ls

14.文件权限属性

setfacl、chmod、chown、chgrp

15.压缩/解压

bzip2/bunzip2、gzip/gunzip、zip/unzip、tar

16.文件传输

ftp、scp

二、Linux系统定时任务

crontab命令

crontab -e

* * * * * 命令(分 时 日 月 周)

//实现每天0点重启服务器
crontab -e
0 0 * * * reboot

三、vi/vim编辑器

1.模式

一般模式、编辑模式和命令行模式

一般模式:删除、复制和粘贴

切换编辑模式:i、I、o、O、a、A、r、R

切换命令行模式有  :、/、?

2.移动光标

ctrl+f、ctrl+b、0或者功能键Home、$或者功能键End、G、gg、N+enter

3.查找和替换

/word、?word、:n1,n2s/word1/word2/g、:1,$s/word1/word2/g、:1,$s/word1/word2/gc

4.删除、复制和粘贴

x、X、dd、ndd、yy、nyy、p、P、ctrl+r、.

5.保存和退出

w、q、wq

6.视图模式(vim)

v、V、ctrl+v、y、d

7.配置

:setnu、:setnonu

四、shell基础

1.脚本执行方式

赋予权限,直接执行。例如

chmod +x test.sh

./test.sh

调用解释器使得脚本执行,例如 bash、csh、ash、bsh、ksh等等

使用source命令,例如 source test.sh

2.编写基础

开头用#!指定脚本解释器,例如 $!/bin/sh

编写具体功能

PHP重要知识复习 – JavaScript、Jquery以及AJAX基础

一、JavaScript基本语法

1.变量的定义

变量必须以字母开头,也能以 $ 或 _ 符号开头;

变量名称对大小写敏感;

使用 var 关键字声明变量;

可以在一条语句中声明多个变量;

var a=1,b=2,c=3;  //可以一次声明多个变量

未使用值来声明的变量,值是 undefined;

如果重新声明 javascript 变量,该变量的值不会丢失;

var a = 12;
var a;
alert(a);  //值仍是12

2.数据类型

字符串、数字、布尔、数组、对象、Null、Undefined

Javascript变量均为对象,当你声明一个变量时,就创建了一个新的对象。

3.函数

使用function定义函数

函数参数不能设置默认值

函数内部声明的变量(使用var)是局部变量

在函数外部声明的变量是全局变量,所有脚本和函数都能访问它。(与php不同)

4.运算符

使用 + 加号连接字符串

5.流程控制

else if 必须分开写(与php不同)

var a = 12;
if (a > 100){
	alert('a 大于 100');
}else if(a > 10){  //这里注意else if要分开写
	alert('a 大于 10');
}else{
	alert('a 小于或等于 10');
}

6.javascript内置对象

创建数组对象  var arr= new Array(‘a’, ‘b’, 2, 48);  //注意Array首字母必须大写

获取时间 var date = new Date();

数学运算 var pi_val = Math.PI;  //获取π的值   var sqrt_val = Math.sqrt(15);  //获取某个值的平方根

正则表达式  var partten = /\d{11}/;  //注意不要用引号   varpartten = new RegExp(partten, attributes);

7.Window对象

Window、Navigator、Screen、History、Location

8.DOM对象

Document、Element、Attr、Event

二、AJAX基础

1.AJAX基本概念

Asynchronous JavaScript and XML

通过在后台与服务器进行少量的数据交换,AJAX可以使网页实现异步更新

2.AJAX工作原理

XMLHttpRequest 是AJAX的基础,XMLHttpRequest用于后台与服务器交换数据

3.Jquery的AJAX操作

$(ele).load()、$.ajax()、$.get()、$.post()、$.getJSON()、$.getScript()

 

PHP重点知识复习 – 网络协议

1.HTTP状态码

当浏览者访问一个网页时,浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含HTTP状态码的信息头(server header)用以响应浏览器的请求。

HTTP状态码的英文为HTTP Status Code。

下面是常见的HTTP状态码:

  • 200 – 请求成功
  • 301 – 资源(网页等)被永久转移到其它URL
  • 404 – 请求的资源(网页等)不存在
  • 500 – 内部服务器错误

此部分内容可以参考 《HTTP状态码》

2.OSI七层协议模型

物理层(Physical) 数据链路层(Data Link) 网络层(Network) 传输层(Transport) 会话层(Session) 表示层(Presentation) 应用层(Application)

OSI七层网络模型

TCP/IP四层概念模型

对应网络协议

应用层(Application) 应用层 HTTP、TFTP, FTP, NFS, WAIS、SMTP
表示层(Presentation) Telnet, Rlogin, SNMP, Gopher
会话层(Session) SMTP, DNS
传输层(Transport) 传输层 TCP, UDP
网络层(Network) 网络层 IP, ICMP, ARP, RARP, AKP, UUCP
数据链路层(Data Link) 数据链路层 FDDI, Ethernet, Arpanet, PDN, SLIP, PPP
物理层(Physical) IEEE 802.1A, IEEE 802.2到IEEE 802.11

此部分内容参考 《OSI七层协议模型》

 

PHP重点知识复习 – 文件及目录处理

1.文件读取/写入

fopen() 用来打开一个文件,打开时需要指定打开模式

打开模式有 r r+ w w+ a a+ x x+

2.不需要fopen打开的函数

file_get_contents()  直接打开一个文件

file_put_contents()  直接将字符串写入到一个文件

file() 将文件内容写入到一个数组

readfile() 读取一个文件,并输出到输出缓冲

3.访问远程文件

如果需要访问远程文件,必须在PHP的配置文件中激活“allow_url_fopen”选项,才能使用fopen( )函数打开远程文件。

HTTP协议打开只能使用只读模式,FTP协议打开使用只读或只写

4.目录操作函数

名称相关:basename()、dirname()、pathinfo()

目录读取:opendir()、readdir()、closedir()、rewinddir()

创建目录:mkdir()

删除目录:rmdir()  注意文件夹内有内容是不能删除的,需要先把里面的内容删除掉。

5.其他函数

filesize() 文件大小

目录大小:disk_free_space()、disk_total_space()

文件类型:filetype()

重命名文件或目录:rename()

此部分参考 《文件系统处理》

解题方法:

牢记文件的操作函数和几种打开模式

理解目录的操作步骤

真题测试:

1.在文件的前面添加”hello world”

$file = './1.txt';

$handle = fopen($file, 'r');

$content = fread($handle, filesize($file));	//注意这里一定要有filesize读取文件大小

$content = 'Hello World'. $content;

fclose($handle);

$handle = fopen($file, 'w');

fwrite($handle, $content);

fclose($handle);

2.通过PHP函数的方式对目录进行遍历,写出程序

$dir = './test';

function loopdir($dir)
{
	$handle = opendir($dir);
	while (false !== ($file = readdir($handle)))	//使用false判断当前目录是否遍历完成
	{
		if ($file != '.' && $file != '..'){	//这里必须排除当前目录(.)和上级目录(..),如果不排除非常危险,而且得不出正确结果
			echo $file. '<br>';
			if (is_dir($dir. '/'. $file)){
				loopdir($dir. '/'. $file);
				closedir($dir. '/'. $file);
			}
		}		
	}
	closedir($handle);
}

loopdir($dir);

 

参考内容:

文件系统处理

文件的上传和下载

 

PHP重点知识复习 – 正则表达式

正则表达式的作用:分割、查找、匹配和替换字符串。

分隔符:正斜线(/)、hash符号(#)以及取反符号(~)。

通用原子:\d \D \s \S \w \W

元字符:. * + ? ^ $ () [] [^] [-] {n} {n,} {n,m} |

模式修正符:i m e s U x A D u

此部分内容参考 《正则表达式》

解题方法:

先写出一个匹配的字符串

自左向右的顺序使用正则表达式的原子和元字符进行拼接

最终加入模式修正符

真题测试:

<?php

$str = '13622815676';

$pattern = '/^\d{11}$/';

preg_match($pattern, $str, $match);

var_dump($match);

$str1 = '<p>abc</p><p>defgg</p>';

$pattern1 = '/<p>(.*?)<\/p>/';

preg_match_all($pattern1, $str1, $match1);

var_dump($match1);

$str2 = '<IMG alt="图片标题" class="reponsive" src="images/abc.jpg"/>';

$pattern2 = '/<img.*?src="(.*?)"\/?>/i';

preg_match($pattern2, $str2, $match2);

var_dump($match2);

$match3 = preg_replace($pattern2, 'xiaofan', $str2);
var_dump($match3);
echo '<hr>';

$str3 = 'http://www.baidu.com/category/123.html';

$pattern3 = '/^http:\/\/.*/';

preg_match($pattern3, $str3, $match4);

var_dump($match4);

$str4 = 'abc7894-6@qq.com.cn';

$pattern4 = '/^[a-zA-Z1-9_-]+@[a-zA-Z1-9_-]+(?:\.[a-zA-Z]+){1,2}$/i';

preg_match($pattern4, $str4, $match5);

var_dump($match5);

 

参考内容:

正则表达式的基础知识

PHP重点知识复习 – 自定义函数及内置函数

1.变量的作用域也称为变量的范围,变量的范围即它定义的上下文背景(也是它的生效范围)。大部分php变量只有一个单独的范围。这个单独的范围跨度同样包含了include和require引入的文件。

函数内的变量是局部变量,如果想在函数内调用全局变量,可以使用global关键字或者使用$GLOBALS以及其他超全局数组。

静态变量,仅在局部函数域中存在,但当程序执行离开此作用域时,其值不会消失。

static 关键字,仅初始化一次,初始化时需要赋值,每次执行函数该值会保留,static修饰的变量是局部的,只在函数内有效,可以记录函数的调用次数,从而可以在某些条件下终止递归。

此部分内容还可以参考:《PHP基础语法》

真题测试:

$count = 5;
function get_count(){
	static $count;
	return $count++;
}

echo $count;
$count++;

echo get_count();
echo get_count();

结果是51;

分析:

$count = 5;
function get_count(){
	static $count;	//静态变量$count与外部的全部变量$count无关,这里初始值是null
	return $count++;	//第一次调用返回null,然后null+1为1
}

echo $count;	//输出5
$count++;	//无输出

echo get_count();	//输入null
echo get_count();	//静态变量$count初始化一次,值一直保留。第二次调用函数输出1

2.函数的参数

默认情况下,函数参数是通过值传递的;如果希望函数修改它的值,可以通过引用传递参数。

$a = 10;
function myFun($a){
	$a = 12;
}
myFun($a);
echo $a;	//输出结果仍为10
echo '<hr>';
$b = 100;
function myFun1(&$b){
	$b = 200;
}
myFun1($b);
echo $b;	//输出结果是200 函数使用引用变量,其值被改变

3.函数的返回值

值通过可选的返回语句(return)返回;

可以返回包括数组和对象的任意类型;

返回语句会中止函数的执行,将控制权交给函数调用处;(也就是函数执行到return后,函数后面的部分将不会再执行)

省略return,返回值为null,不可有多个返回值。(如果有多个值可以用数组进行返回)

4.函数的引用返回

从函数返回一个引用,必须在函数声明和指派返回值给一个变量时都使用引用运算符 &。

function &myFun(){
	static $b = 10;	//这里必须用static静态变量,普通变量实现不了这个效果
	return $b;
}

echo myFun();	//输出结果10
$a = &myFun();	//引用返回
$a = 100;	
echo myFun();	//输出结果100

5.外部文件的导入

include/require语句包含并运行指定文件

如果给出路径名按照路径来找,否则从include_path(这个值是在php.ini里面设置)里面查找

如果include_path中也没有,则从调用脚本文件所在的目录和当前工作目录中查找

当一个文件被包含时,其中所包含的代码也继承了include所在行的变量范围

加载过程中未找到文件则include结构会发出一个警告;这一点和require不同,后者会发出一个致命错误

require在出错时会产生E_COMPILE_ERROR级别的错误。换句话说将导致脚本中止而include只产生警告(E_WARNING),脚本会继续执行。

6.系统内置函数

时间日期函数 date()、strtotime()、mktime()、time()、microtime()、date_default_timezone_set()

打印函数 print() printf() print_r() echo sprintf() var_dump() var_export()

IP处理函数 ip2long() long2ip()

字符串函数

数组函数

常用内置函数整理:常用函数.xls

参考其他内容:

数据函数 

字符串函数

时间函数

 

PHP重点知识复习 – 数组的遍历方式以及流程控制

一、数组遍历的三种方式

for循环遍历、foreach遍历、while list() each()组合遍历

区别:

1.for循环只能遍历索引数组;foreach和while list each组合都可以遍历索引数组和关联数组;

2.foreach遍历时会重置数组指针,也就是会进行reset()操作;

3.while list each组合不会reset()。

二、分支结构

1.if…elseif 分支结构

在elseif语句中只能有一个表达式为true,即在elseif语句中只能有一个语句块被执行,多个elseif从句是排斥关系。

使用elseif语句中有一个基本原则,总把优先范围小的条件放在前面处理。也就是可能越大的条件就越往前面放

2.switch…case 分支结构

和if不同的是,switch后面的控制表达式的数据类型只能是整型、浮点类型或字符串

continue语句作用到switch的作用类似于break。跳出switch外的循环,可以使用continue 2。

for($i = 1; $i < 10; $i++){
	switch ($i){
		case 5:
		echo '这里是continue跳出 <br>';
		continue;	//类似于break 跳出switch分支
		case 7:
		echo '这里是continue2跳出 <br>';
		continue 2;	//使用continue 2 将跳出本次for循环,不输出7
	}
	echo $i. '<br>';
}

switch…case 会生成跳转表,会直接跳转到对应的case。

如果条件比一个简单的比较要复杂得多或者一个很多次得循环中,那么用switch语句可能会更快一些

真题测试:

PHP中如何优化多个if…elseif语句得情况?

答:

1.可以将可能性更大得条件放在前面判断;

2.如果控制表达式为整型、浮点型或字符串,可以用switch…case分支语句。