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

$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

报告分类bash

for file in *.pdf; do mkdir -p -- "${file%%-*}" && \
    mv -- "$file" "${file%%-*}"; done
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

[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

常用设计模式

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