$1易混淆点

一、标准输入和参数的区别

这个问题一定是最容易让人迷惑的,具体来说,就是搞不清什么时候用管道 符| 和文件重定向> ,< ,什么时候用变量$ 。

比如说,我现在有个自动连接宽带的 shell 脚本 connect.sh ,存在我的家目录:

1
2
$ where connect.sh 
/home/fdl/bin/connect.sh

如果我想删除这个脚本,而且想少敲几次键盘,应该怎么操作呢?我曾经这
样尝试过:

1
$ where connect.sh | rm

实际上,这样操作是错误的,正确的做法应该是这样的:

1
$ rm $(where connect.sh)

前者试图将 where 的结果连接到 rm 的标准输入,后者试图将结果作为命令行参数传入。

标准输入就是编程语言中诸如 scanf 或者 readline 这种命令;而参数是指 程序的 main 函数传入的 args 字符数组

前文「Linux文件描述符」说过,管道符和重定向符是将数据作为程序的标 准输入,而 $(cmd) 是读取 cmd 命令输出的数据作为参数。

用刚才的例子说, rm 命令源代码中肯定不接受标准输入,而是接收命令行 参数,删除相应的文件。作为对比, cat 命令是既接受标准输入,又接受 命令行参数:

1
2
3
4
5
6
$ cat filename 
...file text...
$ cat < filename
...file text...
$ echo 'hello world' | cat
hello world

如果命令能够让终端阻塞,说明该命令接收标准输入,反之就是不接受,比 如你只运行 cat 命令不加任何参数,终端就会阻塞,等待你输入字符串并 回显相同的字符串。

二、后台运行程序

比如说你远程登录到服务器上,运行一个 Django web 程序:

1
$ python manager.py runserver 0.0.0.0 Listening on 0.0.0.0:8080...

现在你可以通过服务器的 IP 地址测试 Django 服务,但是终端此时就阻塞 了,你输入什么都不响应,除非输入 Ctrl-C 或者 Ctrl-/ 终止 python 进程。

可以在命令之后加一个 & 符号,这样命令行不会阻塞,可以响应你后续输 入的命令,但是如果你退出服务器的登录,就不能访问该网⻚了。

如果你想在退出服务器之后仍然能够访问web服务,应该这样写命令 (cmd &) :

1
2
3
$ (python manager.py runserver 0.0.0.0 &) Listening on 0.0.0.0:8080...

$ logout

底层原理是这样的:

每一个命令行终端都是一个 shell 进程,你在这个终端里执行的程序实际上 都是这个 shell 进程分出来的子进程。正常情况下,shell 进程会阻塞,等待 子进程退出才重新接收你输入的新的命令。加上 & 号,只是让 shell 进程不 再阻塞,可以继续响应你的新命令。但是无论如何,你如果关掉了这个 shell 命令行端口,依附于它的所有子进程都会退出。

而 (cmd &) 这样运行命令,则是将 cmd 命令挂到一个 systemd 系统守护进程名下,认 systemd 做爸爸,这样当你退出当前终端时,对于刚才的 cmd 命令就完全没有影响了。

类似的,还有一种后台运行常用的做法是这样:

1
$ nohub some_cmd &

nohub 命令也是类似的原理,不过通过我的测试,还是 (cmd &) 这种形式 更加稳定

三、单引号和双引号的区别

不同的 shell 行为会有细微区别,但有一点是确定的,对于 $ ( ) 这 几个符号,单引号包围的字符串不会做任何转义,双引号包围的字符串会转 义

shell 的行为可以测试,使用 set -x 命令,会开启 shell 的命令回显,你可 以通过回显观察 shell 到底在执行什么命令:

可⻅ echo $(cmd) 和 echo “$(cmd)” ,结果差不多,但是仍然有区别。注 意观察,双引号转义完成的结果会自动增加单引号,而前者不会。

也就是说,如果 $ 读取出的参数字符串包含空格,应该用双引号括起来, 否则就会出错

四、****sudo 找不到命令

有时候我们普通用户可以用的命令,用 sudo 加权限之后却报错 command not found:

1
2
3
4
5
$ connect.sh
network-manager: Permission denied

$ sudo connect.sh
sudo: command not found

原因在于, connect.sh 这个脚本仅存在于该用户的环境变量中:

当使用 sudo 时,系统会使用 /etc/sudoers 这个文件中规定的该用户的权 限和环境变量,而这个脚本在 /etc/sudoers 环境变量目录中当然是找不到 的。

解决方法是使用脚本文件的路径,而不是仅仅通过脚本名称:

1
$ sudo /home/fdl/bin/connect.sh
l

§1效率

输入相似文件名太麻烦

用花括号括起来的字符串用逗号连接,可以自动扩展,非常有用,直接看例子:

1
2
3
4
$ echo {one,two,three}file
onefile twofile threefile
$ echo {one,two,three}{1,2,3}
one1 one2 one3 two1 two2 two3 three1 three2 three3

你看,花括号中的每个字符都可以和之后(或之前)的字符串进行组合拼 接,注意花括号和其中的逗号不可以用空格分隔,否则会被认为是普通的字 符串对待

这个技巧有什么实际用处呢?最简单有用的就是给 cp , mv , rm 等命令扩 展参数:

1
2
3
4
5
6
7
8
9
$ cp /very/long/path/file{,.bak}
==> cp /very/long/path/file /very/long/path/file.bak
# 给 file 复制一个叫做 file.bak 的副本

$ rm file{1,3,5}.txt
# 删除 file1.txt file3.txt file5.txt

$ mv *.{c,cpp} src/
# 将所有 .c 和 .cpp 为后缀的文件移入 src 文件夹

输入路径名称太麻烦

  • cd - 返回刚才呆的目录,直接看例子吧:
1
2
3
4
5
6
7
$ pwd
/very/long/path
$ cd # 回到家目录瞅瞅
$ pwd
/home/labuladong
$ cd - # 再返回刚才那个目录 $ pwd
/very/long/path
  • 特殊命令 !$ 会替换成上一次输入的命令最后的路径,直接看例子:
1
2
3
4
5
6
7
#没有加可执行权限
$ /usr/bin/script.sh
zsh: permission denied: /usr/bin/script.sh

$ chmod +x !$
chmod +x /usr/bin/script.sh
export lessCharset-uft8

特殊命令 !* 会替换成上一次命令输入的所有文件路径,直接看例子:

1
2
3
4
5
6
# 创建了三个脚本文件
$ file script1.sh script2.sh script3.sh

# 给它们全部加上可执行权限
$ chmod +x !*
chmod +x script1.sh script2.sh script3.sh

可以在环境变量 CDPATH 中加入你常用的工作目录,当 cd 命令在当前目 录中找不到你指定的文件/目录时,会自动到 CDPATH 中的目录中寻找。

比如说我常去 /var/log 目录找日志,可以执行如下命令:

1
2
3
4
5
6
7
8
9
$ export CDPATH='~:/var/log'
# cd 命令将会在 〜 目录和 /var/log 目录扩展搜索$ pwd
/home/labuladong/musics
$ cd mysql
cd /var/log/mysql
$ pwd
/var/log/mysql
$ cd my_pictures
cd /home/labuladong/my_pictures

这个技巧是十分好用的,这样就免了经常写完整的路径名称,节约不少时间。

需要注意的是,以上操作是 bash 支持的,其他主流 shell 解释器当然都支持 扩展 cd 命令的搜索目录,但可能不是修改 CDPATH 这个变量,具体的设 置方法可以自行搜索。

输入重复命令太麻烦

** 使用特殊命令 !! ,可以自动替换成上一次使用的命令:

1
2
3
4
5
$ apt install net-tools
E: Could not open lock file - open (13: Permission denied)

$ sudo !!
sudo apt install net-tools [sudo] password for fdl:

有的命令很⻓,一时间想不起来具体参数了怎么办?

对于 bash 终端,可以使用 Ctrl+R 快捷键反向搜索历史命令,之所以说是 反向搜索,就是搜索最近一次输入的命令。

比如按下 Ctrl+R 之后,输入 sudo ,bash 就会搜索出最近一次包含 sudo 的命令,你回⻋之后就可以运行该命令了:

1
(reverse-i-search)`sudo': sudo apt install git

但是这个方法有缺点:首先,该功能似乎只有 bash 支持,我用的 zsh 作为 shell 终端,就用不了;第二,只能查找出一个(最近的)命令,如果我想 找以前的某个命令,就没办法了。

对于这种情况,我们最常用的方法是使用 history 命令配合管道符和 grep 命令来寻找某个历史命令:

1
2
3
4
5
6
# 过滤出所有包含 config 字段的历史命令
$ history | grep 'config'
7352 ./configure
7434 git config --global --unset https.proxy 9609 ifconfig
9985 clip -o | sed -z 's/\n/,\n/g' | clip
10433 cd ~/.config

你使用的所有 shell 命令都会被记录,前面的数字就表示这是第几个命令, 找到你想重复使用的命令后,也不需要复制粘贴该命令,只要使用 ! + 你 想重用的命令编号即可运行该命令
拿上面的例子,我想重新运行 git config 那条命令,就可以这样:

1
2
$ !7434
git config --global --unset https.proxy # 运行完成

我觉得 history 加管道加 grep 这样打的字还是太多,可以在 你的 shell 配置文件中( .bashrc , .zshrc 等) 中写这样一个函数:

1
2
3
his() {
history | grep "$@"
}

这样就不需要写那么多,只需要 his ‘some_keyword’ 即可搜索历史命令。

我一般不使用 bash 作为终端,我给大家推荐一款很好用的 shell 终端叫做 zsh,这也是我自己使用的 shell。这款终端还可以扩展各种插件,非常好 用,具体配置方法可自行搜索。

其他小技巧

  • **yes 命令自动输入字符y **进行确认

    我们安装某些软件的时候,可能有交互式的提问:

1
2
3
$ sudo apt install XXX
...
XXX will use 996 MB disk space, continue? [y/n]

一般情况下我们都是一路 y 到底,但如果我们想自动化一些软件的安装就很 烦,遇到这种交互式提问就卡住了,还得手动处理。

yes 命令可以帮助我们:

1
$ yes | your_cmd

这样就会一路自动 y 下去,不会停下让我们输入了。 如果你读过前文Linux 文件描述符,就知道其原理很简单:

你单独运行一下 yes 命令,发现它就是打印出一大堆字符 y,通过管道把 输出和 your_cmd 的标准输入相连接,如果 your_cmd 又提出无聊的问题, 就会从标准输入读取数据,也就会读取到一个 y 和换行符,和你手动输入 y 确认是一个效果。

  • 特殊变量 $? 记录上一次命令的返回值

在 Linux shell 中,遵循 C 语言的习惯,返回值为 0 的话就是程序正常退 出,非 0 值就是异常退出出。读取上一次命令的返回值在平时使用命令行时 感觉没什么用,但是如果你想编写一些 shell 脚本,知道返回值非常有用。

举个实际的例子,比如我的 Github 仓库 fucking-algorithm ,我需要给其中 所有 markdown 文件最下方添加上一篇、下一篇、目录三个⻚脚链接,有的 文章已经有了⻚脚,大部分都没有。

为了防止重复添加,我必须知道一个 md 文件下方是否已添加,这时候就可 以使用 $? 变量配合 grep 命令做到:

1
2
3
4
5
6
#!/bin/bash
filename=$1
# 查看文件尾部是否包含关键词
tail | grep '下一篇' $filename
# grep 查找到匹配会返回 0,找不到则返回非 0 值
[ $? -ne 0 ] && { 添加⻚脚; }
  • 特殊变量 $$ 记录当前进程的 PID

这个功能可能在平时使用时也不怎么用,但是在写 shell 脚本时也非常有 用,比如说你要在 /tmp 创建临时文件,给文件起名字一直都是非常让人 费脑子 的,这时候可以使用 $$ 变量扩展出当前进程的 PID 作为临时文件的名字。

l

[toc]

§1效率

输入相似文件名太麻烦

用花括号括起来的字符串用逗号连接,可以自动扩展,非常有用,直接看例子:

1
2
3
4
$ echo {one,two,three}file
onefile twofile threefile
$ echo {one,two,three}{1,2,3}
one1 one2 one3 two1 two2 two3 three1 three2 three3

你看,花括号中的每个字符都可以和之后(或之前)的字符串进行组合拼 接,注意花括号和其中的逗号不可以用空格分隔,否则会被认为是普通的字 符串对待

这个技巧有什么实际用处呢?最简单有用的就是给 cp , mv , rm 等命令扩 展参数:

1
2
3
4
5
6
7
8
9
$ cp /very/long/path/file{,.bak}
==> cp /very/long/path/file /very/long/path/file.bak
# 给 file 复制一个叫做 file.bak 的副本

$ rm file{1,3,5}.txt
# 删除 file1.txt file3.txt file5.txt

$ mv *.{c,cpp} src/
# 将所有 .c 和 .cpp 为后缀的文件移入 src 文件夹

输入路径名称太麻烦

  • cd - 返回刚才呆的目录,直接看例子吧:
1
2
3
4
5
6
7
$ pwd
/very/long/path
$ cd # 回到家目录瞅瞅
$ pwd
/home/labuladong
$ cd - # 再返回刚才那个目录 $ pwd
/very/long/path
  • 特殊命令 !$ 会替换成上一次输入的命令最后的路径,直接看例子:
1
2
3
4
5
6
7
#没有加可执行权限
$ /usr/bin/script.sh
zsh: permission denied: /usr/bin/script.sh

$ chmod +x !$
chmod +x /usr/bin/script.sh
export lessCharset-uft8

特殊命令 !* 会替换成上一次命令输入的所有文件路径,直接看例子:

1
2
3
4
5
6
# 创建了三个脚本文件
$ file script1.sh script2.sh script3.sh

# 给它们全部加上可执行权限
$ chmod +x !*
chmod +x script1.sh script2.sh script3.sh

可以在环境变量 CDPATH 中加入你常用的工作目录,当 cd 命令在当前目 录中找不到你指定的文件/目录时,会自动到 CDPATH 中的目录中寻找。

比如说我常去 /var/log 目录找日志,可以执行如下命令:

1
2
3
4
5
6
7
8
9
$ export CDPATH='~:/var/log'
# cd 命令将会在 〜 目录和 /var/log 目录扩展搜索$ pwd
/home/labuladong/musics
$ cd mysql
cd /var/log/mysql
$ pwd
/var/log/mysql
$ cd my_pictures
cd /home/labuladong/my_pictures

这个技巧是十分好用的,这样就免了经常写完整的路径名称,节约不少时间。

需要注意的是,以上操作是 bash 支持的,其他主流 shell 解释器当然都支持 扩展 cd 命令的搜索目录,但可能不是修改 CDPATH 这个变量,具体的设 置方法可以自行搜索。

输入重复命令太麻烦

** 使用特殊命令 !! ,可以自动替换成上一次使用的命令:

1
2
3
4
5
$ apt install net-tools
E: Could not open lock file - open (13: Permission denied)

$ sudo !!
sudo apt install net-tools [sudo] password for fdl:

有的命令很⻓,一时间想不起来具体参数了怎么办?

对于 bash 终端,可以使用 Ctrl+R 快捷键反向搜索历史命令,之所以说是 反向搜索,就是搜索最近一次输入的命令。

比如按下 Ctrl+R 之后,输入 sudo ,bash 就会搜索出最近一次包含 sudo 的命令,你回⻋之后就可以运行该命令了:

1
(reverse-i-search)`sudo': sudo apt install git

但是这个方法有缺点:首先,该功能似乎只有 bash 支持,我用的 zsh 作为 shell 终端,就用不了;第二,只能查找出一个(最近的)命令,如果我想 找以前的某个命令,就没办法了。

对于这种情况,我们最常用的方法是使用 history 命令配合管道符和 grep 命令来寻找某个历史命令:

1
2
3
4
5
6
# 过滤出所有包含 config 字段的历史命令
$ history | grep 'config'
7352 ./configure
7434 git config --global --unset https.proxy 9609 ifconfig
9985 clip -o | sed -z 's/\n/,\n/g' | clip
10433 cd ~/.config

你使用的所有 shell 命令都会被记录,前面的数字就表示这是第几个命令, 找到你想重复使用的命令后,也不需要复制粘贴该命令,只要使用 ! + 你 想重用的命令编号即可运行该命令
拿上面的例子,我想重新运行 git config 那条命令,就可以这样:

1
2
$ !7434
git config --global --unset https.proxy # 运行完成

我觉得 history 加管道加 grep 这样打的字还是太多,可以在 你的 shell 配置文件中( .bashrc , .zshrc 等) 中写这样一个函数:

1
2
3
his() {
history | grep "$@"
}

这样就不需要写那么多,只需要 his ‘some_keyword’ 即可搜索历史命令。

我一般不使用 bash 作为终端,我给大家推荐一款很好用的 shell 终端叫做 zsh,这也是我自己使用的 shell。这款终端还可以扩展各种插件,非常好 用,具体配置方法可自行搜索。

其他小技巧

  • **yes 命令自动输入字符y **进行确认

    我们安装某些软件的时候,可能有交互式的提问:

1
2
3
$ sudo apt install XXX
...
XXX will use 996 MB disk space, continue? [y/n]

一般情况下我们都是一路 y 到底,但如果我们想自动化一些软件的安装就很 烦,遇到这种交互式提问就卡住了,还得手动处理。

yes 命令可以帮助我们:

1
$ yes | your_cmd

这样就会一路自动 y 下去,不会停下让我们输入了。 如果你读过前文Linux 文件描述符,就知道其原理很简单:

你单独运行一下 yes 命令,发现它就是打印出一大堆字符 y,通过管道把 输出和 your_cmd 的标准输入相连接,如果 your_cmd 又提出无聊的问题, 就会从标准输入读取数据,也就会读取到一个 y 和换行符,和你手动输入 y 确认是一个效果。

  • 特殊变量 $? 记录上一次命令的返回值

在 Linux shell 中,遵循 C 语言的习惯,返回值为 0 的话就是程序正常退 出,非 0 值就是异常退出出。读取上一次命令的返回值在平时使用命令行时 感觉没什么用,但是如果你想编写一些 shell 脚本,知道返回值非常有用。

举个实际的例子,比如我的 Github 仓库 fucking-algorithm ,我需要给其中 所有 markdown 文件最下方添加上一篇、下一篇、目录三个⻚脚链接,有的 文章已经有了⻚脚,大部分都没有。

为了防止重复添加,我必须知道一个 md 文件下方是否已添加,这时候就可 以使用 $? 变量配合 grep 命令做到:

1
2
3
4
5
6
#!/bin/bash
filename=$1
# 查看文件尾部是否包含关键词
tail | grep '下一篇' $filename
# grep 查找到匹配会返回 0,找不到则返回非 0 值
[ $? -ne 0 ] && { 添加⻚脚; }
  • 特殊变量 $$ 记录当前进程的 PID

这个功能可能在平时使用时也不怎么用,但是在写 shell 脚本时也非常有 用,比如说你要在 /tmp 创建临时文件,给文件起名字一直都是非常让人 费脑子 的,这时候可以使用 $$ 变量扩展出当前进程的 PID 作为临时文件的名字。

l

报告分类bash

for file in *.pdf; do mkdir -p -- "${file%%-*}" && \
    mv -- "$file" "${file%%-*}"; done
l

explain结果每个字段的含义说明

我们都知道用explain xxx分析sql语句的性能,但是具体从explain的结果怎么分析性能以及每个字段的含义你清楚吗?这里我做下总结记录,也是供自己以后参考。

  • 首先需要注意:MYSQL 5.6.3以前只能EXPLAIN SELECT; MYSQL5.6.3以后就可以EXPLAIN SELECT,UPDATE,DELETE

explain结果示例:

1
2
3
4
5
6
7
mysql> explain select * from staff;
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | staff | ALL | NULL | NULL | NULL | NULL | 2 | NULL |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
1 row in set

先上一个官方文档表格的中文版:

Column 含义
id 查询序号
select_type 查询类型
table 表名
partitions 匹配的分区
type join类型
prossible_keys 可能会选择的索引
key 实际选择的索引
key_len 索引的长度
ref 与索引作比较的列
rows 要检索的行数(估算值)
filtered 查询条件过滤的行数的百分比
Extra 额外信息

这是explain结果的各个字段,分别解释下含义:

1. id

SQL查询中的序列号。

id列数字越大越先执行,如果说数字一样大,那么就从上往下依次执行。

2. select_type

查询的类型,可以是下表的任何一种类型:

select_type 类型说明
SIMPLE 简单SELECT(不使用UNION或子查询)
PRIMARY 最外层的SELECT
UNION UNION中第二个或之后的SELECT语句
DEPENDENT UNION UNION中第二个或之后的SELECT语句取决于外面的查询
UNION RESULT UNION的结果
SUBQUERY 子查询中的第一个SELECT
DEPENDENT SUBQUERY 子查询中的第一个SELECT, 取决于外面的查询
DERIVED 衍生表(FROM子句中的子查询)
MATERIALIZED 物化子查询
UNCACHEABLE SUBQUERY 结果集无法缓存的子查询,必须重新评估外部查询的每一行
UNCACHEABLE UNION UNION中第二个或之后的SELECT,属于无法缓存的子查询

DEPENDENT 意味着使用了关联子查询。

3. table

查询的表名。不一定是实际存在的表名。
可以为如下的值:

  • <unionM,N>: 引用id为M和N UNION后的结果。
  • : 引用id为N的结果派生出的表。派生表可以是一个结果集,例如派生自FROM中子查询的结果。
  • : 引用id为N的子查询结果物化得到的表。即生成一个临时表保存子查询的结果。

4. type(重要)

这是最重要的字段之一,显示查询使用了何种类型。从最好到最差的连接类型依次为:

system,const,eq_ref,ref,fulltext,ref_or_null,index_merge,unique_subquery,index_subquery,range,index,ALL

除了all之外,其他的type都可以使用到索引,除了index_merge之外,其他的type只可以用到一个索引。

  • 1、system

表中只有一行数据或者是空表,这是const类型的一个特例。且只能用于myisam和memory表。如果是Innodb引擎表,type列在这个情况通常都是all或者index

  • 2、const

最多只有一行记录匹配。当联合主键或唯一索引的所有字段跟常量值比较时,join类型为const。其他数据库也叫做唯一索引扫描

  • 3、eq_ref

多表join时,对于来自前面表的每一行,在当前表中只能找到一行。这可能是除了system和const之外最好的类型。当主键或唯一非NULL索引的所有字段都被用作join联接时会使用此类型。

eq_ref可用于使用’=’操作符作比较的索引列。比较的值可以是常量,也可以是使用在此表之前读取的表的列的表达式。

相对于下面的ref区别就是它使用的唯一索引,即主键或唯一索引,而ref使用的是非唯一索引或者普通索引。
eq_ref只能找到一行,而ref能找到多行。

  • 4、ref

对于来自前面表的每一行,在此表的索引中可以匹配到多行。若联接只用到索引的最左前缀或索引不是主键或唯一索引时,使用ref类型(也就是说,此联接能够匹配多行记录)。

ref可用于使用’=’或’<=>’操作符作比较的索引列。

  • 5、 fulltext

使用全文索引的时候是这个类型。要注意,全文索引的优先级很高,若全文索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引

  • 6、ref_or_null

跟ref类型类似,只是增加了null值的比较。实际用的不多。

1
2
3
eg.
SELECT * FROM ref_table
WHERE key_column=expr OR key_column IS NULL;
  • 7、index_merge

表示查询使用了两个以上的索引,最后取交集或者并集,常见and ,or的条件使用了不同的索引,官方排序这个在ref_or_null之后,但是实际上由于要读取多个索引,性能可能大部分时间都不如range

  • 8、unique_subquery

用于where中的in形式子查询,子查询返回不重复值唯一值,可以完全替换子查询,效率更高。
该类型替换了下面形式的IN子查询的ref:
value IN (SELECT primary_key FROM single_table WHERE some_expr)

  • 9、index_subquery

该联接类型类似于unique_subquery。适用于非唯一索引,可以返回重复值。

  • 10、range

索引范围查询,常见于使用 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, IN()或者like等运算符的查询中。

1
2
3
4
5
SELECT * FROM tbl_name
WHERE key_column BETWEEN 10 and 20;

SELECT * FROM tbl_name
WHERE key_column IN (10,20,30);
  • 11、index

索引全表扫描,把索引从头到尾扫一遍。这里包含两种情况:
一种是查询使用了覆盖索引,那么它只需要扫描索引就可以获得数据,这个效率要比全表扫描要快,因为索引通常比数据表小,而且还能避免二次查询。在extra中显示Using index,反之,如果在索引上进行全表扫描,没有Using index的提示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 此表见有一个name列索引。
# 因为查询的列name上建有索引,所以如果这样type走的是index
mysql> explain select name from testa;
+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
| 1 | SIMPLE | testa | index | NULL | idx_name | 33 | NULL | 2 | Using index |
+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
1 row in set

# 因为查询的列cusno没有建索引,或者查询的列包含没有索引的列,这样查询就会走ALL扫描,如下:
mysql> explain select cusno from testa;
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | testa | ALL | NULL | NULL | NULL | NULL | 2 | NULL |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
1 row in set

# 包含有未见索引的列
mysql> explain select * from testa;
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | testa | ALL | NULL | NULL | NULL | NULL | 2 | NULL |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
1 row in set
  • 12、all

全表扫描,性能最差。

5. partitions

版本5.7以前,该项是explain partitions显示的选项,5.7以后成为了默认选项。该列显示的为分区表命中的分区情况。非分区表该字段为空(null)。

6. possible_keys

查询可能使用到的索引都会在这里列出来

7. key

查询真正使用到的索引。
select_type为index_merge时,这里可能出现两个以上的索引,其他的select_type这里只会出现一个。

8. key_len

查询用到的索引长度(字节数)。
如果是单列索引,那就整个索引长度算进去,如果是多列索引,那么查询不一定都能使用到所有的列,用多少算多少。留意下这个列的值,算一下你的多列索引总长度就知道有没有使用到所有的列了。

key_len只计算where条件用到的索引长度,而排序和分组就算用到了索引,也不会计算到key_len中。

9. ref

如果是使用的常数等值查询,这里会显示const,如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段,如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func

10. rows(重要)

rows 也是一个重要的字段。 这是mysql估算的需要扫描的行数(不是精确值)。
这个值非常直观显示 SQL 的效率好坏, 原则上 rows 越少越好.

11. filtered

这个字段表示存储引擎返回的数据在server层过滤后,剩下多少满足查询的记录数量的比例,注意是百分比,不是具体记录数。这个字段不重要

12. extra(重要)

EXplain 中的很多额外的信息会在 Extra 字段显示, 常见的有以下几种内容:

  • distinct:在select部分使用了distinc关键字
  • Using filesort:当 Extra 中有 Using filesort 时, 表示 MySQL 需额外的排序操作, 不能通过索引顺序达到排序效果. 一般有 Using filesort, 都建议优化去掉, 因为这样的查询 CPU 资源消耗大.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 例如下面的例子:

mysql> EXPLAIN SELECT * FROM order_info ORDER BY product_name \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: order_info
partitions: NULL
type: index
possible_keys: NULL
key: user_product_detail_index
key_len: 253
ref: NULL
rows: 9
filtered: 100.00
Extra: Using index; Using filesort
1 row in set, 1 warning (0.00 sec)
我们的索引是

KEY `user_product_detail_index` (`user_id`, `product_name`, `productor`)
但是上面的查询中根据 product_name 来排序, 因此不能使用索引进行优化, 进而会产生 Using filesort.
如果我们将排序依据改为 ORDER BY user_id, product_name, 那么就不会出现 Using filesort 了. 例如:

mysql> EXPLAIN SELECT * FROM order_info ORDER BY user_id, product_name \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: order_info
partitions: NULL
type: index
possible_keys: NULL
key: user_product_detail_index
key_len: 253
ref: NULL
rows: 9
filtered: 100.00
Extra: Using index
1 row in set, 1 warning (0.00 sec)
  • Using index
    “覆盖索引扫描”, 表示查询在索引树中就可查找所需数据, 不用扫描表数据文件, 往往说明性能不错
  • Using temporary
    查询有使用临时表, 一般出现于排序, 分组和多表 join 的情况, 查询效率不高, 建议优化.

除此之外还有其他值,这里就不一一一列举了。


通过以上这些总结,以后我们看到explain的结果,就知道该从哪些字段值去分析sql语句的执行效率了。

l

mysql 连表操作后字符集不同导致索引失效

背景

一个表的字符集为utf8mb4
一个表的字符集为utf8

连表查询后可以发现索引失效的情况,查询很慢。

t1为utf8,t2为utf8mb4。但是为什么表字符集不一样(实际是字段字符集不一样)就会导致t1全表扫描呢?

分析原因

(1)首先t2 left join t1决定了t2是驱动表,这一步相当于执行了

1
select * from t2 where t2.name = 'dddd'

取出code字段的值,假如为’8a77a32a7e0825f7c8634226105c42e5’;

(2)然后拿t2查到的code的值根据join条件去t1里面查找,这一步就相当于执行了

1
select * from t1 where t1.code = '8a77a32a7e0825f7c8634226105c42e5';

(3)但是由于第(1)步里面t2表取出的code字段是utf8mb4字符集,而t1表里面的code是utf8字符集,这里需要做字符集转换,字符集转换遵循由小到大的原则,因为utf8mb4是utf8的超集,所以这里把utf8转换成utf8mb4,即把t1.code转换成utf8mb4字符集,转换了之后,由于t1.code上面的索引仍然是utf8字符集,所以这个索引会被执行计划忽略了,然后t1表只能选择全表扫描。如果t2筛选出来的记录不止1条,那么t1就会被多次全表扫描,性能之差可想而知。

修改字符集

1
alter table t1 charset utf8mb4;

这是错的,这只是改了表的默认字符集,即新的字段才会使用utf8mb4,已经存在的字段仍然是utf8。

1
alter table t1 convert to charset utf8mb4;

查看 SHOW FULL COLUMNS FROM t1 ;会发现字段的字符已经改变。

其他

排序规则概念:是指对指定字符集下不同字符的比较规则。排序规则有以下特征:

  • 它和字符集(CHARSET)相关
  • 每种字符集都有多种它支持的排序规则
  • 每种字符集都会默认指定一种排序规则为默认值。
  • mysql可对相应字符集,单独设置排序规则

排序规则作用:排序规则指定后,它会影响我们使用 ORDER BY语句查询的结果顺序,会影响到 WHERE条件中大于小于号的筛选结果,会影响 DISTINCT、GROUP BY、HAVING 语句的查询结果。另外,mysql 建索引的时候,如果索引列是字符类型,也会影响索引创建,只不过这种影响我们感知不到。总之,凡是涉及到字符类型比较或排序的地方,都和排序规则有关。

注意点

  • 表字符集不同时,可能导致join的SQL使用不到索引,引起严重的性能问题;
  • 建表语句一定要设置默认字符集,需要关联的表字符集一定要统一;
  • 统一dev、fat、test、prod环境mysql对应库的字符集,可以及早发现问题;
l

mysql 连表操作后字符集不同导致索引失效

背景

一个表的字符集为utf8mb4
一个表的字符集为utf8

连表查询后可以发现索引失效的情况,查询很慢。这时候可以通过show warnings;查询警告信息。发现了convert(testdb.t1.code using utf8mb4)之后,发现2个表的字符集不一样。

t1为utf8,t2为utf8mb4。但是为什么表字符集不一样(实际是字段字符集不一样)就会导致t1全表扫描呢?下面来做分析。

分析原因

(1)首先t2 left join t1决定了t2是驱动表,这一步相当于执行了

1
select * from t2 where t2.name = 'dddd'

取出code字段的值,这里为’8a77a32a7e0825f7c8634226105c42e5’;

(2)然后拿t2查到的code的值根据join条件去t1里面查找,这一步就相当于执行了

1
select * from t1 where t1.code = '8a77a32a7e0825f7c8634226105c42e5';

(3)但是由于第(1)步里面t2表取出的code字段是utf8mb4字符集,而t1表里面的code是utf8字符集,这里需要做字符集转换,字符集转换遵循由小到大的原则,因为utf8mb4是utf8的超集,所以这里把utf8转换成utf8mb4,即把t1.code转换成utf8mb4字符集,转换了之后,由于t1.code上面的索引仍然是utf8字符集,所以这个索引就被执行计划忽略了,然后t1表只能选择全表扫描。如果t2筛选出来的记录不止1条,那么t1就会被多次全表扫描,性能之差可想而知。

修改字符集

1
alter table t1 charset utf8mb4;

但这是错的,这只是改了表的默认字符集,即新的字段才会使用utf8mb4,已经存在的字段仍然是utf8。
show create table t1 会发现DEFAULT CHARSET=utf8mb4改变了,但是SHOW FULL COLUMNS FROM pay_log_all_from_mq;会发现字段的字符集没有改变。

1
alter table t1 convert to charset utf8mb4;

查看 SHOW FULL COLUMNS FROM t1 ;会发现字段的字符已经改变。

注意点

  • 表字符集不同时,可能导致join的SQL使用不到索引,引起严重的性能问题;
l

[toc]

开篇词

第零章、必读系列

学习算法和刷题的框架思维

动态规划解题套路框架

回溯算法解题套路框架

BFS 算法解题套路框架

我写了首诗,让你闭着眼睛也能写对二分搜索

我写了首诗,把滑动窗口算法算法变成了默写题

一个方法团灭 LeetCode 股票买卖问题

一个方法团灭 LeetCode 打家劫舍问题

一个方法团灭 nSum 问题

经典动态规划:高楼扔鸡蛋

经典动态规划:子集背包问题

经典动态规划:完全背包问题

表达式求值算法:实现计算器

第一章、动态规划系列

动态规划解题套路框架

动态规划答疑篇

动态规划和回溯算法到底谁是谁爹?

动态规划设计:最⻓递增子序列

动态规划设计:最大子数组

经典动态规划:0-1 背包问题

经典动态规划:子集背包问题

经典动态规划:完全背包问题

经典动态规划:编辑距离

经典动态规划:高楼扔鸡蛋

经典动态规划:高楼扔鸡蛋(进阶)

经典动态规划:戳气球

经典动态规划:最⻓公共子序列

动态规划之子序列问题解题模板

动态规划之博弈问题

动态规划之正则表达

动态规划之四键键盘

动态规划之KMP字符匹配算法

贪心算法之区间调度问题

团灭 LeetCode 股票买卖问题

团灭 LeetCode 打家劫舍问题

第二章、数据结构系列

学习数据结构和算法读什么书

算法学习之路

二叉堆详解实现优先级队列

LRU算法详解

二叉搜索树操作集锦

如何计算完全二叉树的节点数

特殊数据结构:单调栈

特殊数据结构:单调队列

设计Twitter 递归反转链表的一部分

队列实现栈|栈实现队列

第三章、算法思维系列

学习算法和刷题的思路指南

回溯算法解题套路框架

回溯算法团灭子集、排列、组合问题

回溯算法最佳实践:解数独

回溯算法最佳实践:括号生成

二分查找详解

双指针技巧总结

滑动窗口技巧

twoSum问题的核心思想

常用的位操作

拆解复杂问题:实现计算器

烧饼排序

前缀和技巧

字符串乘法

FloodFill算法详解及应用

区间调度之区间合并问题

区间调度之区间交集问题

信封嵌套问题

几个反直觉的概率问题

第四章、高频面试系列

如何实现LRU算法

如何用 BFS 算法秒杀各种智力题

如何高效寻找素数

如何高效进行模幂运算

如何计算编辑距离

如何运用二分查找算法

如何高效解决接雨水问题

如何去除有序数组的重复元素

如何寻找最⻓回文子串

如何运用贪心思想玩跳跃游戏

如何k个一组反转链表

如何判定括号合法性

如何寻找缺失的元素

如何同时寻找缺失和重复的元素

如何判断回文链表

如何在无限序列中随机抽取元素

如何调度考生的座位

Union-Find算法详解

Union-Find算法应用

一行代码就能解决的算法题

二分查找高效判定子序列

第五章、技术文章系列

Linux的进程、线程、文件描述符是什么

关于 Linux shell 你必须知道的

Linux shell 的实用小技巧

加密算法的前身今世

我用四个命令概括了 Git 的所有套路

Git/SQL/正则表达式的在线练习平台

l

规则

abcdefghijklmnopqurtuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZa
abced
abd

A[A-Z]{24}Z
abbabbbc
abbc
abc
ac

ab{5}c

ab((ce)?d)?

10^6ml
10^9ML
10E9 ML

10[^E][369] ?(ml|ML)

ad
1234567890
[^\s]
Ha HaHa
.转义
[abc]
[^abc]
[a-z]
[^a-z]
[a-zA-Z]
.
\s\S space
\w\W word
\d\D digit
(a|b)
a? 0-1次
a* 0-任意次
a+ 1-任意次
a{3} 3次
a{3,6} 三到六次
a{,6} 至多6次
a{3,} 至少三次
(a{3}|a{6}) 3次或6次
^ 开头
$ 结尾

MetaCharacters (Need to be escaped):
.[{()^$|?*+

coreyms.com
[-a-zA-Z0-9./]+.[a-zA-Z]+/?

\d{3}[.-]\d{3}[.-]\d{4}

192.168.0.1
255.255.255.255

[1-9]?\d|1\d{2}|2([0-4]\d|5[0-5])

(([1-9]?\d|1\d{2}|2([0-4]\d|5[0-5])).){3}([1-9]?\d|1\d{2}|2([0-4]\d|5[0-5])))

321-555-4321
123.555.1234

Mr. Schafer
Mr Smith
Ms Davis
Mrs. Robinson
Mr. T
Mr. t

M(s|r|rs).? [A-Z][a-z]*

https://deerchao.net/tutorials/regex/regex.htm
https://regex101.com/
https://www.regular-expressions.info/

练习

Dave Martin
615-555-7164
173 Main St., Springfield RI 55924
davemartin@bogusemail.com

Charles Harris
800-555-5669
969 High St., Atlantis VA 34075
charlesharris@bogusemail.com

Eric Williams
560-555-5153
806 1st St., Faketown AK 86847
laurawilliams@bogusemail.com

Corey Jefferson
900-555-9340
826 Elm St., Epicburg NE 10671
coreyjefferson@bogusemail.com

Jennifer Martin-White
714-555-7405
212 Cedar St., Sunnydale CT 74983
jenniferwhite@bogusemail.com

Erick Davis
800-555-6771
519 Washington St., Olympus TN 32425
tomdavis@bogusemail.com

Neil Patterson
783-555-4799
625 Oak St., Dawnstar IL 61914
neilpatterson@bogusemail.com

Laura Jefferson
516-555-4615
890 Main St., Pythonville LA 29947
laurajefferson@bogusemail.com

Maria Johnson
127-555-1867
884 High St., Braavos‎ ME 43597
mariajohnson@bogusemail.com

Michael Arnold
608-555-4938
249 Elm St., Quahog OR 90938
michaelarnold@bogusemail.com

Michael Smith
568-555-6051
619 Park St., Winterfell VA 99000
michaelsmith@bogusemail.com

Erik Stuart
292-555-1875
220 Cedar St., Lakeview NY 87282
robertstuart@bogusemail.com

Laura Martin
900-555-3205
391 High St., Smalltown WY 28362
lauramartin@bogusemail.com

Barbara Martin
614-555-1166
121 Hill St., Braavos‎ UT 92474
barbaramartin@bogusemail.com

Linda Jackson
530-555-2676
433 Elm St., Westworld TX 61967
lindajackson@bogusemail.com

Eric Miller
470-555-2750
838 Main St., Balmora MT 56526
stevemiller@bogusemail.com

Dave Arnold
800-555-6089
732 High St., Valyria KY 97152
davearnold@bogusemail.com

Jennifer Jacobs
880-555-8319
217 High St., Old-town IA 82767
jenniferjacobs@bogusemail.com

Neil Wilson
777-555-8378
191 Main St., Mordor IL 72160
neilwilson@bogusemail.com

Kurt Jackson
998-555-7385
607 Washington St., Blackwater NH 97183
kurtjackson@bogusemail.com

Mary Jacobs
800-555-7100
478 Oak St., Bedrock IA 58176
maryjacobs@bogusemail.com

Michael White
903-555-8277
906 Elm St., Mordor TX 89212
michaelwhite@bogusemail.com

Jennifer Jenkins
196-555-5674
949 Main St., Smalltown SC 96962
jenniferjenkins@bogusemail.com

Sam Wright
900-555-5118
835 Pearl St., Smalltown ND 77737
samwright@bogusemail.com

John Davis
905-555-1630
451 Lake St., Bedrock GA 34615
johndavis@bogusemail.com

Eric Davis
203-555-3475
419 Lake St., Balmora OR 30826
neildavis@bogusemail.com

Laura Jackson
884-555-8444
443 Maple St., Quahog MS 29348
laurajackson@bogusemail.com

John Williams
904-555-8559
756 Hill St., Valyria KY 94854
johnwilliams@bogusemail.com

Michael Martin
889-555-7393
216 High St., Olympus NV 21888
michaelmartin@bogusemail.com

Maggie Brown
195-555-2405
806 Lake St., Lakeview MD 59348
maggiebrown@bogusemail.com

Erik Wilson
321-555-9053
354 Hill St., Mordor FL 74122
kurtwilson@bogusemail.com

Elizabeth Arnold
133-555-1711
805 Maple St., Winterfell NV 99431
elizabetharnold@bogusemail.com

Jane Martin
900-555-5428
418 Park St., Metropolis ID 16576
janemartin@bogusemail.com

Travis Johnson
760-555-7147
749 Washington St., Braavos‎ SD 25668
travisjohnson@bogusemail.com

Laura Jefferson
391-555-6621
122 High St., Metropolis ME 29540
laurajefferson@bogusemail.com

Tom Williams
932-555-7724
610 High St., Old-town FL 60758
tomwilliams@bogusemail.com

Jennifer Taylor
609-555-7908
332 Main St., Pythonville OH 78172
jennifertaylor@bogusemail.com

Erick Wright
800-555-8810
858 Hill St., Blackwater NC 79714
jenniferwright@bogusemail.com

Steve Doe
149-555-7657
441 Elm St., Atlantis MS 87195
stevedoe@bogusemail.com

Kurt Davis
130-555-9709
404 Oak St., Atlantis ND 85386
kurtdavis@bogusemail.com

Corey Harris
143-555-9295
286 Pearl St., Vice City TX 57112
coreyharris@bogusemail.com

Nicole Taylor
903-555-9878
465 Hill St., Old-town LA 64102
nicoletaylor@bogusemail.com

Elizabeth Davis
574-555-3194
151 Lake St., Eerie SD 17880
elizabethdavis@bogusemail.com

Maggie Jenkins
496-555-7533
504 Lake St., Gotham PA 46692
maggiejenkins@bogusemail.com

Linda Davis
210-555-3757
201 Pine St., Vice City AR 78455
lindadavis@bogusemail.com

Dave Moore
900-555-9598
251 Pine St., Old-town OK 29087
davemoore@bogusemail.com

Linda Jenkins
866-555-9844
117 High St., Bedrock NE 11899
lindajenkins@bogusemail.com

Eric White
669-555-7159
650 Oak St., Smalltown TN 43281
samwhite@bogusemail.com

Laura Robinson
152-555-7417
377 Pine St., Valyria NC 78036
laurarobinson@bogusemail.com

Charles Patterson
893-555-9832
416 Pearl St., Valyria AK 62260
charlespatterson@bogusemail.com

Joe Jackson
217-555-7123
683 Cedar St., South Park KS 66724
joejackson@bogusemail.com

Michael Johnson
786-555-6544
288 Hill St., Smalltown AZ 18586
michaeljohnson@bogusemail.com

Corey Miller
780-555-2574
286 High St., Springfield IA 16272
coreymiller@bogusemail.com

James Moore
926-555-8735
278 Main St., Gotham KY 89569
jamesmoore@bogusemail.com

Jennifer Stuart
895-555-3539
766 Hill St., King’s Landing GA 54999
jenniferstuart@bogusemail.com

Charles Martin
874-555-3949
775 High St., Faketown PA 89260
charlesmartin@bogusemail.com

Eric Wilks
800-555-2420
885 Main St., Blackwater OH 61275
joewilks@bogusemail.com

Elizabeth Arnold
936-555-6340
528 Hill St., Atlantis NH 88289
elizabetharnold@bogusemail.com

John Miller
372-555-9809
117 Cedar St., Thundera NM 75205
johnmiller@bogusemail.com

Corey Jackson
890-555-5618
115 Oak St., Gotham UT 36433
coreyjackson@bogusemail.com

Sam Thomas
670-555-3005
743 Lake St., Springfield MS 25473
samthomas@bogusemail.com

Patricia Thomas
509-555-5997
381 Hill St., Blackwater CT 30958
patriciathomas@bogusemail.com

Jennifer Davis
721-555-5632
125 Main St., Smalltown MT 62155
jenniferdavis@bogusemail.com

Patricia Brown
900-555-3567
292 Hill St., Gotham WV 57680
patriciabrown@bogusemail.com

Barbara Williams
147-555-6830
514 Park St., Balmora NV 55462
barbarawilliams@bogusemail.com

James Taylor
582-555-3426
776 Hill St., Dawnstar MA 51312
jamestaylor@bogusemail.com

Eric Harris
400-555-1706
421 Elm St., Smalltown NV 72025
barbaraharris@bogusemail.com

Travis Anderson
525-555-1793
937 Cedar St., Thundera WA 78862
travisanderson@bogusemail.com

Sam Robinson
317-555-6700
417 Pine St., Lakeview MD 13147
samrobinson@bogusemail.com

Steve Robinson
974-555-8301
478 Park St., Springfield NM 92369
steverobinson@bogusemail.com

Mary Wilson
800-555-3216
708 Maple St., Braavos‎ UT 29551
marywilson@bogusemail.com

Sam Wilson
746-555-4094
557 Pearl St., Westworld KS 23225
samwilson@bogusemail.com

Charles Jones
922-555-1773
855 Hill St., Olympus HI 81427
charlesjones@bogusemail.com

Laura Brown
711-555-4427
980 Maple St., Smalltown MO 96421
laurabrown@bogusemail.com

Tom Harris
355-555-1872
676 Hill St., Blackwater AR 96698
tomharris@bogusemail.com

Patricia Taylor
852-555-6521
588 Pine St., Olympus FL 98412
patriciataylor@bogusemail.com

Barbara Williams
691-555-5773
351 Elm St., Sunnydale GA 26245
barbarawilliams@bogusemail.com

Maggie Johnson
332-555-5441
948 Cedar St., Quahog DE 56449
maggiejohnson@bogusemail.com

Kurt Miller
900-555-7755
381 Hill St., Quahog AL 97503
kurtmiller@bogusemail.com

Neil Stuart
379-555-3685
496 Cedar St., Sunnydale RI 49113
neilstuart@bogusemail.com

Linda Patterson
127-555-9682
736 Cedar St., Lakeview KY 47472
lindapatterson@bogusemail.com

Charles Davis
789-555-7032
678 Lake St., Mordor MN 11845
charlesdavis@bogusemail.com

Jennifer Jefferson
783-555-5135
289 Park St., Sunnydale WA 74526
jenniferjefferson@bogusemail.com

Erick Taylor
315-555-6507
245 Washington St., Bedrock IL 26941
coreytaylor@bogusemail.com

Robert Wilks
481-555-5835
573 Elm St., Sunnydale IL 47182
robertwilks@bogusemail.com

Travis Jackson
365-555-8287
851 Lake St., Metropolis PA 22772
travisjackson@bogusemail.com

Travis Jackson
911-555-7535
489 Oak St., Atlantis HI 73725
travisjackson@bogusemail.com

Laura Wilks
681-555-2460
371 Pearl St., Smalltown SC 47466
laurawilks@bogusemail.com

Neil Arnold
274-555-9800
504 Oak St., Faketown PA 73860
neilarnold@bogusemail.com

Linda Johnson
800-555-1372
667 High St., Balmora IN 82473
lindajohnson@bogusemail.com

Jennifer Wilson
300-555-7821
266 Pine St., Westworld DC 58720
jenniferwilson@bogusemail.com

Nicole White
133-555-3889
276 High St., Braavos‎ IL 57764
nicolewhite@bogusemail.com

Maria Arnold
705-555-6863
491 Elm St., Metropolis PA 31836
mariaarnold@bogusemail.com

Jennifer Davis
215-555-9449
859 Cedar St., Old-town MT 31169
jenniferdavis@bogusemail.com

Mary Patterson
988-555-6112
956 Park St., Valyria CT 81541
marypatterson@bogusemail.com

Jane Stuart
623-555-3006
983 Oak St., Old-town RI 15445
janestuart@bogusemail.com

Robert Davis
192-555-4977
789 Maple St., Mordor IN 22215
robertdavis@bogusemail.com

James Taylor
178-555-4899
439 Hill St., Olympus NV 39308
jamestaylor@bogusemail.com

Eric Stuart
952-555-3089
777 High St., King’s Landing AZ 16547
johnstuart@bogusemail.com

Charles Miller
900-555-6426
207 Washington St., Blackwater MA 24886
charlesmiller@bogusemail.com

  • ip正则:
    (((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5])).){3}((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))
l

设计模式2

1.观察者模式

  • 定义:在对象之间定义了一对多的依赖,这样的话,当一个对象改变状态,依赖他的对象会受到通知并自动更新。(其实就是发布订阅模式:发布者发布信息,订阅者获取信息,订阅了就能收到消息,没订阅的就收不到消息)

2.访问者模式

  • 定义:封装作用于某种数据结构中各元素的操作,它可在不改变数据结构的前提下定义作用于这些元素的新的操作。

3.命令模式

  • 定义:发送者和接收者之间引入了一个命令对象,将发送者的请求封装在命令对象中,再通过命令对象来调用接受者的方法。
  • spring框架:spring是怎么做的,view、controller、service是怎么连在一起的:spring是控制反转、依赖注入,解决了数据数据初始化一些问题,能够吧代码写得很简洁,然后脱颖而出,核心是怎么做的,数据初始化是怎么做的。面向切面的编程可以用在什么地方,spring的一般框架是mvc
    :层是controller、中间层是service、底层是dao。为什么这么分?他比其他的区别是什么?对一些request包装了
    找spring一两点深入研究:我不仅仅是用了spring,我还研究了他某一个组件,他是怎么实现的?讲讲(闪光点)
  • velocity(模板语言)
    我用了velocity,我发现了velocity里的很多东西和我学的java、c++都是一样的,他这个框架他把一些公用的都提取出来,前面的spring boot是个java框架,为什么要用velocity,因为我要前后端分离,view和后面的数据要分离,data是怎么传过来的,怎么解析的,他支持什么东西?(不仅仅用了这个东西,还有思想,解耦)

    3.mybatis

  • 怎么把数据库的一些前后的读取给做了,怎么把xml里的多重条件,怎么做文法的解析,然后把这些条件给处理掉。

    4.登录/注册

  • 网站安全(salt):密码为什么加了一个salt就变得安全?
  • 通过拦截器来实现的:拦截器的思想、框架,留好接口;拦截器实现登录注册:我在cookie里放了一个token,token怎么处理用户登录注册的:在用户登录注册的时候,会下发一个token,把token与用户信息关联起来,关联起来之后我为了优化token信息,把token放到数据库里(redis),设计一个分布式的统一登录系统,现在的互联网产品都是统一登录的,比如,登录qq之后,登录网页就不需要登录了,qq登录过的token直接注入到网页上去。这是个ssension共享问题:、
  • 保证数据安全:验证(邮件激活)

    5.前缀树

  • 构造一个前缀树,通过一个有限状态机来实现一传文本是不是包含敏感词,繁杂度是多少 很重要:优点有哪些?为什么不用kmp,文本查找算法:
    可以很快的加一些词汇过来;有扩展性,以及性能更提高

    6.redis

  • 数据结构:跳列表,哈希,优先队列,list:我了解redis底层是怎么实现的,为什么他的效率很高,他的字符串是怎么保存的,做这个工程的时候我用在的异步队列上、排序上、异步框架

    7.异步框架

*思路:我这个网站附带的每一步操作可能附带的操作都非常多,为了更快的吧结果返回给用户,所以采用异步框架,自己写的,数据结构:使用redis的队列,因为redis能够保证线程同步;除了用队列,我还想过用有优先队列,这样我的异步框架能够把紧急的任务线处理掉。我这个异步框架:有消息的发射,消息的处理,事件的模型定义以及具体执行的eventhandle,我定义了一些公共接口把这些实现了。

8.邮件(smtp协议)

  • 做了一个简单邮件,怎么连接上服务器,我当时做这个的时候,ssl问题
    ,ssl理解,服务器需要ssl链接,为了安全服务器是怎么做的;java sdk 1.7 1.8的问题,1.8是需要换一个jar包的
  • 豆瓣电影排序:好的问题能挑选出来,互动越多,时间越新,评分越高。

    9.timeline(时间轴)

  • 肯定会问:为什么用推拉模式,用推实时性高能让好友快速得到消息,用拉能节省僵尸号、不是活跃用户的存储空间。怎么区分?最后把timeline组合起来‘timeline模板系统,每个新鲜事展向不一样,和velocity结合起来,后台存储的都是核心数据,每个数据对应的是一个模板,我把模板结合起来,我就能快速的把时间轴展示出来。

    10.爬虫

    11.solr搜索

  • 搜索去重:对比相似度,敏感哈希算法,哈希算法:两个字符串稍微有一点点不一样,结构就是不一样的。可能头尾是不一样的,内容一样:采用敏感哈希算法把相似度求出来,区别:敏感哈希算法两个文档相似度很高,他生成的哈希值的比例是很相似的。

    12.单元测试/部署

  • 部署:运维,llinux nigix反向代理,与正向对比。负载均衡:为什么要负载均衡。
l