Docker相关指令

docker镜像运行以及日志

1
2
3
❯ docker run --restart=always -d --name holer-client -e PARAMS="www.swimminghao.top 6060 51c45156bf1c4a82b4e6ffff2150b65e" swimminghao/holer-client:latest
❯ docker run -d --name holer-server --restart=always --network=host -p 600:600 -p 6060:6060 -p 6443:6443 -p 11000-11010:11000-11010 swimminghao/holer-server:latest
❯ docker logs -f 1ed9a5d6f0cc

Dockerfile 打包jar成docker镜像

1
2
3
4
5
6
7
dockerfile1
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD ./holer-client.jar holer-client.jar
RUN echo "Asia/Shanghai" > /etc/timezone
ENV PARAMS=
ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -Duser.timezone=GMT+8 -jar /holer-client.jar ${PARAMS}
1
2
3
4
5
6
7
8
9
dockerfile2
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD ./holer-client.jar holer-client.jar
RUN echo "Asia/Shanghai" > /etc/timezone
ENV PARAMS=
ENV JVM_XMS="256m"
ENV JVM_XMX="256m"
ENTRYPOINT java -Xms${JVM_XMS} -Xmx${JVM_XMX} -Djava.security.egd=file:/dev/./urandom -Duser.timezone=GMT+8 -jar /holer-client.jar ${PARAMS}

dockerfile和jar包放同一文件夹,再执行下面指令

1
❯ docker build -t swimminghao/holer-client:latest .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
FROM openjdk:8-jdk-alpine
VOLUME /tmp

ARG JAR_FILE=./holer-server.jar
#ARG PORT=8090
ARG TIME_ZONE=Asia/Shanghai

ENV TZ=${TIME_ZONE}
ENV JVM_XMS="256m"
ENV JVM_XMX="256m"

COPY ${JAR_FILE} holer-server.jar

EXPOSE 600
EXPOSE 6060
EXPOSE 6443

ENTRYPOINT java -Xms${JVM_XMS} -Xmx${JVM_XMX} -Djava.security.egd=file:/dev/./urandom -server -jar holer-server.jar

dockerfile和jar包放同一文件夹,再执行下面指令

1
❯ docker build -t swimminghao/holer-server:latest .

docker容器停止以及镜像删除

1
2
3
4
5
❯ docker ps -a
❯ docker pull seanhongxing/holer-server
❯ docker stop f8ca94969ba0 && docker rm f8ca94969ba0
❯ docker image ls -a
❯ docker image rm f8ca94969ba0

docker镜像反推Dockerfile:

1、指令

1
❯ docker history <83d576a828a8> --format "{{.CreatedBy}}" --no-trunc |tac | awk '{if($3~/nop/){for(i=1;i<=3;i++){$i=""};print substr($0,4)}else{print "RUN",$0}}'

2、bash脚本

1
❯ bash decompile.sh seanhongxing/holer-server
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
#!/bin/bash
#########################################################################
# File Name: dockerfile.sh
# Author: www.linuxea.com
# Version: 1
# Created Time: Thu 14 Feb 2019 10:52:01 AM CST
#########################################################################
case "$OSTYPE" in
linux*)
docker history --no-trunc --format "{{.CreatedBy}}" $1 | # extract information from layers
tac | # reverse the file
sed 's,^\(|3.*\)\?/bin/\(ba\)\?sh -c,RUN,' | # change /bin/(ba)?sh calls to RUN
sed 's,^RUN #(nop) *,,' | # remove RUN #(nop) calls for ENV,LABEL...
sed 's, *&& *, \\\n \&\& ,g' # pretty print multi command lines following Docker best practices
;;
darwin*)
docker history --no-trunc --format "{{.CreatedBy}}" $1 | # extract information from layers
tail -r | # reverse the file
sed -E 's,^(\|3.*)?/bin/(ba)?sh -c,RUN,' | # change /bin/(ba)?sh calls to RUN
sed 's,^RUN #(nop) *,,' | # remove RUN #(nop) calls for ENV,LABEL...
sed $'s, *&& *, \\\ \\\n \&\& ,g' # pretty print multi command lines following Docker best practices
;;
*)
echo "unknown OSTYPE: $OSTYPE"
;;
esac

docker镜像下载jar包

1
2
3
4
//镜像导出
❯ docker save -o ./client.tar seanhongxing/holer-client:latest
//容器导出
❯ docker export seanhongxing/holer-client > ./client.tar

注:分层,jar包在某一层

l

git reset放弃修改&放弃增加文件

1. 本地修改了一堆文件(并没有使用git add到暂存区),想放弃修改。
单个文件/文件夹:

1
$ git checkout -- filename

所有文件/文件夹:

1
$ git checkout .

2. 本地新增了一堆文件(并没有git add到暂存区),想放弃修改。
单个文件/文件夹:

1
$ rm filename / rm dir -rf

所有文件/文件夹:

1
$ git clean -xdf

// 删除新增的文件,如果文件已经已经git add到暂存区,并不会删除!

3. 本地修改/新增了一堆文件,已经git add到暂存区,想放弃修改。
单个文件/文件夹:

1
$ git reset HEAD filename

所有文件/文件夹:

1
$ git reset HEAD .

4. 本地通过git add & git commit 之后,想要撤销此次commit

1
$ git reset commit_id

这个id是你想要回到的那个节点,可以通过git log查看,可以只选前6位
// 撤销之后,你所做的已经commit的修改还在工作区!

1
$ git reset --hard commit_id

这个id是你想要回到的那个节点,可以通过git log查看,可以只选前6位
// 撤销之后,你所做的已经commit的修改将会清除,仍在工作区/暂存区的代码不会清除!

l

github 上传大文件100MB姿势

具体就是安装git-lfs,先下载,然后就是一顿操作:

  1. 先在web建立一个空仓库

  2. 然后建立跟仓库名一样的文件夹,并执行初始化命令:git init

  3. 然后执行git lfs install

  4. 然后添加你要上传的文件名或后缀名:git lfs track '*.zip'

  5. 然后就把生成的 .gitattributes文件,先传到远程仓库

    • git add .gitattributes
  • git commit -m 'large - init file'
    • git push -u origin master:master # 第一次要这样执行,后面再传就git push就行。
  1. 然后就可以正常添加上传大文件了!

    • git add bigfile.zip
    • git commit -m 'upload Big file.'
    • git push # 第一次要这样执行,后面再传就git push就行。

  • 删除远程仓库文件,但本地文件不删除,如

    1
    bigfile.zip
    • git rm bigfile.zip
    • git commit -m 'rm bigfile.zip'
    • git push
l

git

git指令

一般来说,日常使用只要记住下图6个命令,就可以了。但是熟练使用,恐怕要记住60~100个命令。

workspace:工作区

Index/Stage:暂存区

Repository:仓库区(或本地仓库)

Remote:远程仓库

  • 述任务及修改内容,填写要发布的前后端应用和提测、上线时间,以及研发负责人、研发人员、测试负责人。
  1. 将测试报告(已解密)通过ftp上传

    • 将上传报告名加到app-sz-artemis中的ReportRecognitionServiceTest类
    • (注)报告提前解密,保证准时完成上线。上传报告名必须以模板名开头:例,xikang1.田淑梅.pdf
  2. 提交项目到dev与release分支

    • 首先commit&push sz-artemis-common 项目(因为sz-artemis-report-parser、sz-artemis-report-api、app-sz-artemis均依赖于它),然后c&p sz-artimis-report-parser,最后c&p app-sz-artemis。
    • (注)先push到dev分支,再push到release分支,release分支严格遵守格式:例,release-2019-09-05
  3. 通过Rocket.chat编译

    • 使用Rocket.chat编译,严格按照步骤3里的顺序,并注意指令正确。每编译完一个项目到http://118.178.137.55:8089/job下查看console output,是否编译成功。
    • (注)指令格式:@Gerty b sz-artemis-common;@Gerty b sz-artemis-report-parser;@Gerty b sz-artemis-api;@Gerty b test_sz-artemis
  4. 自测

    • 通过识别回归测试工具,进行自测,查看测试通过的状况以及与以往测试用例集相异的excel结果
    • 若excel结果无差异,或差异在可接受范围以内,则测试通过,并将本次测试产生的测试用例覆盖历史测试用例。
    • 测试通过则可上线。
  5. 发jira链接

    • 链接发顾璟琛审核,之后发方雷部署。

 

l

git 流程

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
正常上线
git clone

git checkout dev

git checkout -b feature-function

git add .
git commit -m '结束功能开发'

git checkout dev
git merge feature-function
git push origin dev

git checkout -b release-2019-09-29
git push origin release-2019-09-29

线上发现bug 紧急上线

git checkout -b hotfix-2019-09-29 origin/master
git checkout -b hotfix-2019-09-29
git add .
git commit -m 'message'
git push origin hotfix-2019-09-29

git checkout dev
git merge hotfix-2019-09-29
git push origin dev


git branch -d feature-function
l

正常上线

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
git clone

git checkout dev

git checkout -b feature-function

git add .
git commit -m '结束功能开发'

git checkout dev
git merge feature-function
git push origin dev

git checkout -b release-2019-09-29
git push origin release-2019-09-29

线上发现bug 紧急上线

git checkout -b hotfix-2019-09-29 origin/master
git checkout -b hotfix-2019-09-29
git add .
git commit -m 'message'
git push origin hotfix-2019-09-29

git checkout dev
git merge hotfix-2019-09-29
git push origin dev


git branch -d feature-function
l

git指令

个人开发

一般来说,日常使用只要记住下图6个命令,就可以了。但是熟练使用,恐怕要记住60~100个命令。

workspace:工作区

Index/Stage:暂存区

Repository:仓库区(或本地仓库)

Remote:远程仓库

  1. 新建代码库

    1
    2
    # 下载一个项目和它的整个代码历史
    $ git clone [url]
  2. 配置

    Git的设置文件为.gitconfig,它可以在用户主目录下(全局配置),也可以在项目目录下(项目配置)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 显示当前的Git配置
    $ git config --list

    # 编辑Git配置文件
    $ git config -e [--global]

    # 设置提交代码时的用户信息
    $ git config [--global] user.name "[name]"
    $ git config [--global] user.email "[email address]"
  3. 增加/删除文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # 添加指定文件到暂存区
    $ git add [file1] [file2] ...

    # 添加指定目录到暂存区,包括子目录
    $ git add [dir]

    # 添加当前目录的所有文件到暂存区
    $ git add .

    # 添加每个变化前,都会要求确认
    # 对于同一个文件的多处变化,可以实现分次提交
    $ git add -p

    # 删除工作区文件,并且将这次删除放入暂存区
    $ git rm [file1] [file2] ...
  4. 代码提交

    1
    2
    3
    4
    5
    6
    7
    8
    # 提交暂存区到仓库区
    $ git commit -m [message]

    # 提交暂存区的指定文件到仓库区
    $ git commit [file1] [file2] ... -m [message]

    # 提交时显示所有diff信息
    $ git commit -v
  5. 分支

    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
    39
    # 列出所有本地分支
    $ git branch

    # 列出所有远程分支
    $ git branch -r

    # 列出所有本地分支和远程分支
    $ git branch -a

    # 新建一个分支,但依然停留在当前分支
    $ git branch [branch-name]

    # 新建一个分支,并切换到该分支
    $ git checkout -b [branch]

    # 新建一个分支,指向指定commit
    $ git branch [branch] [commit]

    # 新建一个分支,与指定的远程分支建立追踪关系
    $ git branch --track [branch] [remote-branch]

    # 切换到指定分支,并更新工作区
    $ git checkout [branch-name]

    # 切换到上一个分支
    $ git checkout -

    # 建立追踪关系,在现有分支与指定的远程分支之间
    $ git branch --set-upstream [branch] [remote-branch]

    # 合并指定分支到当前分支
    $ git merge [branch]

    # 删除分支
    $ git branch -d [branch-name]

    # 删除远程分支
    $ git push origin --delete [branch-name]
    $ git branch -dr [remote/branch]
  6. 查看信息

    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    # 显示有变更的文件
    $ git status

    # 显示当前分支的版本历史
    $ git log

    # 显示commit历史,以及每次commit发生变更的文件
    $ git log --stat

    # 搜索提交历史,根据关键词
    $ git log -S [keyword]

    # 显示某个文件的版本历史,包括文件改名
    $ git log --follow [file]
    $ git whatchanged [file]

    # 显示指定文件相关的每一次diff
    $ git log -p [file]

    # 显示过去5次提交
    $ git log -5 --pretty --oneline

    # 显示所有提交过的用户,按提交次数排序
    $ git shortlog -sn

    # 显示指定文件是什么人在什么时间修改过
    $ git blame [file]

    # 显示暂存区和工作区的差异
    $ git diff

    # 显示暂存区和上一个commit的差异
    $ git diff --cached [file]

    # 显示工作区与当前分支最新commit之间的差异
    $ git diff HEAD

    # 显示两次提交之间的差异
    $ git diff [first-branch]...[second-branch]

    # 显示某次提交的元数据和内容变化
    $ git show [commit]

    # 显示某次提交发生变化的文件
    $ git show --name-only [commit]

    # 显示某次提交时,某个文件的内容
    $ git show [commit]:[filename]

    # 显示当前分支的最近几次提交
    $ git reflog
  7. 远程同步

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    # 下载远程仓库的所有变动
    $ git fetch [remote]

    # 显示所有远程仓库
    $ git remote -v

    # 显示某个远程仓库的信息
    $ git remote show [remote]

    # 增加一个新的远程仓库,并命名
    $ git remote add [shortname] [url]

    # 取回远程仓库的变化,并与本地分支合并
    $ git pull [remote] [branch]

    # 上传本地指定分支到远程仓库
    $ git push [remote] [branch]

    # 推送所有分支到远程仓库
    $ git push [remote] --all
  8. 撤销

    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
    # 恢复暂存区的指定文件到工作区
    $ git checkout [file]

    # 恢复某个commit的指定文件到暂存区和工作区
    $ git checkout [commit] [file]

    # 恢复暂存区的所有文件到工作区
    $ git checkout .

    # 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变
    $ git reset [file]

    # 重置暂存区与工作区,与上一次commit保持一致
    $ git reset --hard

    # 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变
    $ git reset [commit]

    # 重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致
    $ git reset --hard [commit]

    # 重置当前HEAD为指定commit,但保持暂存区和工作区不变
    $ git reset --keep [commit]

    # 新建一个commit,用来撤销指定commit
    # 后者的所有变化都将被前者抵消,并且应用到当前分支
    $ git revert [commit]

    # 暂时将未提交的变化移除,稍后再移入
    $ git stash
    $ git stash pop

    多人合作开发

    1. 源仓库

      项目开始的时候,项目发起者构建起一个项目的最原始的仓库,称之为源仓库(origin)。

      • 源仓库有两个作用
        1. 汇总参与该项目的各个开发者的代码
        2. 存放趋于稳定和可发布的代码
      • 源仓库受到保护,开发者不直接对其进行开发工作。只有项目管理者能对其进行较高权限的操作。
    2. 开发者仓库

      如上所说,任何开发者都不会对源仓库进行直接的操作,源仓库建立以后,每个开发者需要fork一份源仓库,作为自己日常开发的仓库。

      每个开发者所fork的仓库是完全独立的,互不干扰。每个开发者仓库相当于一个源仓库实体的镜像,开发者在这个镜像中进行编码,提交到自己的仓库中,这样就可以轻易地实现团队成员之间的并行开发工作。而开发工作完成以后,开发者可以向源仓库发送pull request,请求管理员把自己的代码合并到源仓库中,这样就实现了分布式开发工作,和最后的集中式的管理。

    3. 分支 (Branch)

      git分支有两类,5种:

      1
      2
      3
      4
      5
      6
      7
      永久性分支
      master branch:主分支
      develop branch:开发分支
      临时性分支
      feature branch:功能分支
      release branch:预发布分支
      hotfix branch:bug修复分支
    4. 多人合作具体步骤

      1)clone远程代码

      1
      git clone [url]

      2)切换到develop分支,将本地新项目提交到本地develop分支,再将本地develp分支上的新建项目将上传到远程develop分支。

      1
      2
      3
      4
      git checkout develop
      git add .
      git commit -m "new branch commit"
      git push origin new branch commit

    3)开发

    • 切换到develop分支

      1
      git checkout develop
    • 分出一个功能性分支

      1
      git checkout -b function-branch
    • 在功能性分支上进行开发工作,多次commit,测试以后

    • 把做好的功能合并到develop中

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      git checkout develop
      # 回到develop分支

      git merge --no-ff function-branch
      # 把做好的功能合并到develop中

      git branch -d functio-branch
      # 删除功能性分支

      git push origin develop
      # 把develop提交到自己的远程仓库中

    4)合并远程master和develop分支

    切换到master分支,从远程pull代码,将develop分支合并到本地master分支(此时本地master分支是与远程同步的),有冲突解决,没有则罢。最后push到远程master仓库。

    (注)保证多人协作的时候尽量少出现merge conflict和污染主分支,做到以下几点:

    • 做好分工,尽量避免出现多人修改同一个文件。

    • 每个人的所有开发工作都只在自己的分支开发。

    • 每个人只允许在自己的分支直接push远程分支。

    • 合并的时候必须遵循以下条件.

      1)首先本地切换到develop分支

      1
      git checkout develop

      2)git pull

      3)那么在pull到远程的develop最新的内容之后,

      1
      git merge  [branch]

      4)如果出现confict那么清除conflict之后,commit。然后把本地develop push到远程develop。

      5)没完成一个功能就提交一次。不要累计代码。

git checkout dev

git push origin –delete release-1.00.00

l

idea .gitignore(git文件忽略)

idea使用git通常需要忽略一些临时文件,需要配置.gitignore插件

  1. 安装插件
    File -> Settings -> Plugins 搜索框搜索.ignore,点击安装

  2. 生成初始.ignore文件

出现如下弹框,会默认生成所选语言的常用忽略项,我这里选java,

img

生成如下文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

idea项目一般需要自己增加如下两项

1
2
.idea/
target/

即忽略这两个文件夹即文件夹下的所有文件

现在可以使用了,提交一次测试下

发现.idea文件夹下的文件还有变更被提交,这是因为在使用gitignore之前,此文件就以及被跟踪了,这样的话需要移除跟踪,如下命令:

移除指定文件夹即文件夹下所有文件:

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
39
40
41
42
43
44
45
46
47
48
49
git rm --cached --force -r .idea 
rm '.idea/artifacts/xxx_api_war.xml'
rm '.idea/artifacts/xxx_api_war_exploded.xml'
rm '.idea/artifacts/xxx_task_war.xml'
rm '.idea/artifacts/xxx_task_war_exploded.xml'
rm '.idea/libraries/Maven__ch_qos_logback_logback_classic_1_1_7.xml'
rm '.idea/libraries/Maven__ch_qos_logback_logback_core_1_1_7.xml'
rm '.idea/libraries/Maven__com_alibaba_druid_1_0_22.xml'
rm '.idea/libraries/Maven__com_alibaba_fastjson_1_2_14.xml'
rm '.idea/libraries/Maven__com_aliyun_openservices_ons_client_1_2_4.xml'
rm '.idea/libraries/Maven__com_fasterxml_aalto_xml_0_9_11.xml'
rm '.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_5_2.xml'
rm '.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_5_2.xml'
rm '.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_5_2.xml'
rm '.idea/libraries/Maven__com_fasterxml_jackson_dataformat_jackson_dataformat_xml_2_5_2.xml'
rm '.idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_jaxb_annotations_2_5_2.xml'
rm '.idea/libraries/Maven__com_google_guava_guava_19_0.xml'
rm '.idea/libraries/Maven__commons_codec_commons_codec_1_9.xml'
rm '.idea/libraries/Maven__commons_httpclient_commons_httpclient_3_1.xml'
rm '.idea/libraries/Maven__commons_logging_commons_logging_1_0_4.xml'
rm '.idea/libraries/Maven__commons_logging_commons_logging_1_2.xml'
rm '.idea/libraries/Maven__javax_servlet_javax_servlet_api_3_1_0.xml'
rm '.idea/libraries/Maven__mysql_mysql_connector_java_5_1_39.xml'
rm '.idea/libraries/Maven__org_apache_commons_commons_lang3_3_3_2.xml'
rm '.idea/libraries/Maven__org_apache_commons_commons_pool2_2_0.xml'
rm '.idea/libraries/Maven__org_apache_httpcomponents_httpclient_4_4.xml'
rm '.idea/libraries/Maven__org_apache_httpcomponents_httpcore_4_4.xml'
rm '.idea/libraries/Maven__org_aspectj_aspectjweaver_1_8_9.xml'
rm '.idea/libraries/Maven__org_codehaus_woodstox_stax2_api_3_1_4.xml'
rm '.idea/libraries/Maven__org_mongodb_mongo_java_driver_2_14_0.xml'
rm '.idea/libraries/Maven__org_mybatis_mybatis_3_4_1.xml'
rm '.idea/libraries/Maven__org_mybatis_mybatis_spring_1_3_0.xml'
rm '.idea/libraries/Maven__org_quartz_scheduler_quartz_2_2_2.xml'
rm '.idea/libraries/Maven__org_slf4j_jcl_over_slf4j_1_7_21.xml'
rm '.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_21.xml'
rm '.idea/libraries/Maven__org_springframework_data_spring_data_commons_1_12_2_RELEASE.xml'
rm '.idea/libraries/Maven__org_springframework_data_spring_data_mongodb_1_9_2_RELEASE.xml'
rm '.idea/libraries/Maven__org_springframework_spring_aop_4_3_1_RELEASE.xml'
rm '.idea/libraries/Maven__org_springframework_spring_aspects_4_3_1_RELEASE.xml'
rm '.idea/libraries/Maven__org_springframework_spring_beans_4_3_1_RELEASE.xml'
rm '.idea/libraries/Maven__org_springframework_spring_context_4_3_1_RELEASE.xml'
rm '.idea/libraries/Maven__org_springframework_spring_context_support_4_3_1_RELEASE.xml'
rm '.idea/libraries/Maven__org_springframework_spring_core_4_3_1_RELEASE.xml'
rm '.idea/libraries/Maven__org_springframework_spring_expression_4_3_1_RELEASE.xml'
rm '.idea/libraries/Maven__org_springframework_spring_jdbc_4_3_1_RELEASE.xml'
rm '.idea/libraries/Maven__org_springframework_spring_tx_4_3_1_RELEASE.xml'
rm '.idea/libraries/Maven__org_springframework_spring_web_4_3_1_RELEASE.xml'
rm '.idea/libraries/Maven__org_springframework_spring_webmvc_4_3_1_RELEASE.xml'
rm '.idea/libraries/Maven__redis_clients_jedis_2_6_2.xml'

移除指定文件:

1
2
git rm --cached --force ydq-api/ydq-api.iml
rm 'ydq-api/ydq-api.iml'

这样,表示移除成功。

现在,上面的操作进行提交:

img

移交移除文件.png

以后再做一些变更,当再次提交时,只有未被忽略的(被忽略的文件的变更再也不会被提交了)修改的文件了。

现在,idea下配置.gitignore结束。

注:
.gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。那么解决方法就是先把本地缓存删除(改变成未track状态),然后再提交:
输入:
git rm -r –cached filePath
git commit -m “remove xx”
或者:
git rm -r –cached .
git add .
git commit -m “update .gitignore”

来解释下几个参数 -r 是删除文件夹及其子目录 –cached 是删除暂存区里的文件而不删除工作区里的文件,第一种是删除某个文件,第二种方法就把所有暂存区里的文件删了,再加一遍,相当于更新了一遍。

l

mac快捷键

图形按键

按键或组合键 功能
Command 键
Control 键
Option 键
Shift 键
Caps Lock
fn 功能键常用快捷键

剪切、拷贝和粘贴

您可以在大多数 app 中使用这些快捷键来剪切、拷贝或粘贴选中的项目。其中包括文本、图片、音乐等等。您甚至可以在 Finder 中拷贝和粘贴文件,来将文件拷贝到新位置。

按键或组合键 功能
Command-C 将所选数据拷贝到剪贴板
Command-X 移除选中的项目,然后将副本放在剪贴板中
Command-V 将剪贴板副本放到(粘贴)到当前文稿或 app 中

拍摄屏幕快照

使用这些快捷键可拍摄一张屏幕内容的照片。您也可以使用 Grab 拍摄屏幕快照,这款 app 位于“实用工具”文件夹中。

按键或组合键 功能
Command-Shift-3 将屏幕捕捉到文件
Command-Shift-Control-3 将屏幕内容捕捉到剪贴板
Command-Shift-4 将所选屏幕内容捕捉到一个文件,或按空格键仅捕捉一个窗口
Command-Shift-Control-4 将所选屏幕内容捕捉到剪贴板,或按空格键仅捕捉一个窗口

启动快捷键

使用这些组合键可更改电脑的启动方式。启动 Mac 后立即按住相关按键或组合键,直到所需的功能出现。例如,启动时按住 Option 键,直到“启动管理器”出现。
注:如果您使用的不是 Apple 制造的键盘,则 Alt 键通常相当于 Option 键。如果此修饰键不起作用,请尝试改用 Apple 键盘。

按键或组合键 功能
Option 或 Alt 显示所有启动宗卷(启动管理器)
Shift 在安全模式下启动
C 从可引导介质(DVD、CD、USB 闪存驱动器)启动
T 在目标磁盘模式下启动
N 从 NetBoot 服务器启动
X 强制 OS X 启动(如果非 OS X 启动宗卷可用)
D 使用 Apple Hardware Test
Command-R 使用 OS X 恢复功能(OS X Lion 或更高版本)
Command-Option-R 在受支持的电脑上使用互联网恢复
Command-V 以详细模式启动
Command-S 以单用户模式启动
Command-Option-P-R 重置 NVRAM
按住介质推出 (⏏) 键、F12 键、鼠标或触控板按钮 推出活动光盘

睡眠、关闭和注销快捷键

Mac 启动后使用这些组合键可让电脑进入睡眠状态、关机、注销或重新启动。

按键或组合键 功能
电源按钮 轻按可开机。在通电后,轻按“电源”按钮可使您的 Mac 唤醒或进入睡眠状态。
按住电源按钮 1.5 秒 显示重新启动/睡眠/关闭对话框
按住电源按钮 5 秒 强制 Mac 关机
Control-电源按钮 显示重新启动/睡眠/关闭对话框
Command-Control-电源按钮 强制 Mac 重新启动
Command-Option-电源按钮 使电脑进入睡眠状态
Command-Control-电源按钮 退出所有 app(会让您先存储对已打开文稿所作的更改),然后重新启动电脑
Command-Option-Control-电源按钮 退出所有 app(会让您先存储对已打开文稿所作的更改),然后关闭电脑
Shift-Control-电源按钮 使所有显示器进入睡眠状态
Command-Shift-Q 注销
Command-Shift-Option-Q 立即注销

App 快捷键

这些键盘快捷键适用于大部分 app。

组合键 功能
Command-A 在最前面的窗口中选择所有项目或文本
Command-Z 撤消上一命令(有些 app 可让您撤消多次)
Command-Shift-Z 重做,恢复上次使用撤消进行的更改(有些 app 可让您重做多次)
Command-空格键 显示或隐藏 Spotlight 搜索栏(如果同时使用多语种,此快捷键可能会转而循环显示启用的脚本系统)
Command-Option-空格键 显示 Spotlight 搜索结果窗口(如果安装了多语种,则可能循环显示某一脚本中的键盘布局和输入法)
Command-Tab 在打开的 app 列表中,向下移动到下一个最近使用的 app
Option-介质推出键 (⏏) 从备选光盘驱动器中推出(如果已安装)
Command-调低亮度 (F1) 切换针对多显示器配置的“镜像显示器”
Command-调高亮度 (F2) 切换目标显示器模式
Command-Mission Control (F3) 显示桌面
Command-F5 切换 VoiceOver 的开关
Option-亮度 (F2) 打开“显示器”系统偏好设置
Option-Mission Control (F3) 打开“Mission Control”偏好设置
Option-音量键 (F12) 打开“声音”偏好设置
Command-减号 (–) 缩小所选项
Command-冒号 (:) 显示“拼写和语法”窗口
Command-分号 (;) 查找文稿中拼写错误的词
Command-逗号 (,) 打开最前面的 app 的偏好设置窗口
Command-问号 (?) 打开“帮助”菜单
Command-加号 (+)或 Command-Shift-等号 (=) 放大所选项
Command-Option-D 显示或隐藏 Dock
Command-Control-D 显示或隐藏选中字词的定义
Command-D 在“打开和存储”对话框中选择“桌面”文件夹
Command-Delete 选择包含“删除”或“不存储”按钮的对话框中的“不存储”
Command-E 使用所选内容进行查找
Command-F 打开“查找”窗口,或在文稿中查找文本
Command-Option-F 移到搜索栏控件
Command-G 查找所选内容出现的下一个位置
Command-Shift-G 查找所选内容出现的上一个位置
Command-H 隐藏当前正在运行的 app 的窗口
Command-Option-H 隐藏所有其他正在运行的 app 的窗口
Command-Option-I 显示检查器窗口
Command-M 将活跃窗口最小化至 Dock
Command-Option-M 将处于活动状态的 app 的所有窗口最小化至 Dock 中
Command-N 在最前面的 app 中创建新文稿
Command-O 显示一个对话框,用于选择要在最前面的 app 中打开的文稿
Command-P 打印当前文稿
Command-Shift-P 显示用于指定文稿参数(页面设置)的对话框
Command-Q 退出最前面的 app
Command-S 存储活跃文稿
Command-Shift-S 显示“存储为”对话框或复制当前文稿
Command-Option-T 显示或隐藏工具栏
Command-W 关闭最前面的窗口
Command-Option-W 关闭当前 app 中的所有窗口
Command-Z 撤消上一命令(有些 app 允许多次撤消)
Command-Shift-Z 重做,恢复上次使用撤消进行的更改(有些 app 可让您重做多次)
Command-Option-esc 选择要强制退出的 app
Command-Shift-Option-Esc(按住三秒钟) 强制退出最前面的 app

对文本进行处理

编辑某个字段或文稿中的文本时可使用这些组合键。

组合键 功能
Command-B 以粗体显示所选文本或切换文本粗体显示开/关
Command-I 以斜体显示所选文本或切换文本斜体显示开/关
Command-U 对所选文本加下划线或打开/关闭加下划线功能
Command-T 显示或隐藏“字体”窗口
fn-Delete 向前删除(适用于便携式 Mac 的内建键盘)
fn-上箭头 向上滚动一页(相当于 Page Up 键)
fn-下箭头 向下滚动一页(相当于 Page Down 键)
fn-左箭头 滚动至文稿开头(相当于 Home 键)
fn-右箭头 滚动至文稿末尾(相当于 End 键)
Command-右箭头 将文本插入点移至当前行的行尾
Command-左箭头 将文本插入点移至当前行的行首
Command-下箭头 将文本插入点移至文稿末尾
Command-上箭头 将文本插入点移至文稿开头
Option-右箭头 将文本插入点移至下一个单词的末尾
Option-左箭头 将文本插入点移至上一个单词的开头
Option-Delete 删除光标左侧的词,以及词后的任何空格或标点符号
Command-Shift-右箭头 选中插入点与当前行行尾之间的文本 (*)
Command-Shift-左箭头 选中插入点与当前行行首之间的文本 (*)
Command-Shift-上箭头 选中插入点与文稿开头之间的文本 (*)
Command-Shift-下箭头 选中插入点与文稿末尾之间的文本 (*)
Shift-左箭头 将文本选择范围向左扩展一个字符 (*)
Shift-右箭头 将文本选择范围向右扩展一个字符 (*)
Shift-上箭头 将文本选择范围扩展到上一行相同水平位置的最近字符边缘 (*)
Shift-下箭头 将文本选择范围扩展到下一行相同水平位置的最近字符边缘 (*)
Shift-Option-右箭头 将文本选择范围扩展到当前词的词尾,再按一次则扩展到后一词的词尾 (*)
Shift-Option-左箭头 将文本选择范围扩展到当前词的词首,再按一次则扩展到后一词的词首 (*)
Shift-Option-下箭头 将文本选择范围扩展到当前段落的段尾,再按一次则扩展到下一段落的结尾 (*)
Shift-Option-上箭头 将文本选择范围扩展到当前段落的段首,再按一次则扩展到下一段落的段首 (*)
Control-A 移至行或段落的开头
Control-B 向后移动一个字符
Control-D 删除光标前的字符
Control-E 移至行或段落的开头
Control-F 向前移动一个字符
Control-H 删除光标后的字符
Control-K 删除从光标前的字符到行或段落末尾的所有内容
Control-L 将光标或所选内容置于可见区域中央
Control-N 下移一行
Control-O 在光标后插入一行
Control-P 上移一行
Control-T 调换光标前后的字符
Control-V 下移
Command-{ 使所选内容左对齐
Command-} 使所选内容右对齐
Command- 使所选内容居中对齐
Command-Option-C 拷贝所选项的格式设置并存储到剪贴板
Command-Option-V 将某对象的样式应用于所选对象(粘贴样式)
Command-Shift-Option-V 将周围文本的样式应用于所插入对象(粘贴并匹配样式)
Command-Control-V 将格式设置应用于所选对象(粘贴标尺)

辅助功能

这些键盘快捷键可帮助您通过键盘或辅助设备控制 Mac。这些快捷键中,有些快捷键需要在“系统偏好设置”的“键盘”面板或“辅助功能”面板中启用。

组合键 功能
Command-Option-F5 显示辅助功能选项
Command-F5 或 fn-Command-F5 打开或关闭 VoiceOver
Option-Control-F8 或 fn-Option-Control-F8 打开 VoiceOver 实用工具(如果 VoiceOver 已打开)
Command-Option-8 打开或关闭缩放功能
Command-Option-加号 (+) 放大
Command-Option-减号 (–) 缩小
Command-Option-Control-8 反转/复原屏幕颜色
Command-Option-Control-逗号 (,) 降低对比度
Command-Option-Control-句点 (.) 增强对比度

全键盘控制

通过全键盘控制,您可以使用键盘进行导航,并与屏幕上的项目进行交互。使用这些快捷键可选择并调整文本栏和滑块等控件。按 Control-F7 或从“系统偏好设置”中“键盘”偏好设置的“快捷键”面板中选择“全键盘控制”,可以切换此设置开/关。

组合键 功能
Tab 移至下一个控件
Shift-Tab 移至上一个控件
Control-Tab 已选择文本栏时移至下一个控件
Shift-Control-Tab 将焦点移至上一组控件
箭头键 移至列表、标签组或菜单中的相邻项,或移动滑块和调节器(用于增加和减小值的垂直上下箭头)
Control-箭头键 移至与文本栏相邻的控件
空格键 选择高亮显示的菜单项
Return 或 Enter 键 点按默认按钮或执行默认操作
Esc 键 点按“取消”按钮,或关闭菜单而不选取项目
Shift-Control-F6 将焦点移至上一个面板
Control-F7 临时覆盖窗口和对话框中的当前键盘访问模式
Control-F8 移到菜单栏中的状态菜单
Command-重音符 (`) 激活最前面的 app 中下一个打开的窗口
Command-Shift-重音符 (`) 激活最前面的 app 中上一个打开的窗口
Command-Option-重音符 (`) 将焦点移至窗口抽屉

您可以在菜单栏中浏览菜单,而无需使用鼠标或触控板。若要将焦点置于菜单栏中,请按 Control-F2(便携式键盘上的 fn-Control-F2)。然后使用下列组合键。

组合键 功能
左箭头和右箭头 从一个菜单移到另一个菜单
Return 打开所选菜单
上箭头和下箭头 移至所选菜单中的菜单项
键入菜单项的名称 跳到所选菜单中的菜单项
Return 选择菜单项

辅助功能 - 鼠标键

在“辅助功能”偏好设置中打开“鼠标键后,您可以使用键盘或数字小键盘上的按键移动鼠标指针。

组合键 功能
8 或数字小键盘上的 8 上移
K 或数字小键盘上的 2 下移
U 或数字小键盘上的 4 左移
O 或数字小键盘上的 6 右移
J 或数字小键盘上的 1 沿对角线向左下角移
L 或数字小键盘上的 3 沿对角线向右下角移
7 或数字小键盘上的 7 沿对角线向左上角移
9 或数字小键盘上的 9 沿对角线向右上角移
I 或数字小键盘上的 5 按鼠标按钮
M 或数字小键盘上的 0 按住鼠标按钮
.(句点键) 释放按住的鼠标按钮

Finder 快捷键

组合键 功能
Command-A 选择最前面的窗口中的所有文件
Command-Option-A 取消选择所有项
Command-C 拷贝选中的文件,然后使用“粘贴”或“移动”来移动这些文件。
Command-D 重复选中的文件
Command-E 推出
Command-F 查找任何匹配 Spotlight 属性的内容
Command-I 显示选中的文件的“显示简介”窗口
Command-Shift-C 打开“电脑”窗口
Command-Shift-D 打开“桌面”文件夹
Command-Shift-F 显示“我的所有文件”窗口
Command-Shift-G 前往文件夹
Command-Shift-H 打开当前已登录用户帐户的个人文件夹
Command-Shift-I 打开 iCloud Drive
Command-Shift-K 打开“网络”窗口
Command-Shift-L 打开“下载”文件夹
Command-Shift-O 打开“文稿”文件夹
Command-Shift-R 打开 AirDrop 窗口
Command-Shift-U 打开“实用工具”文件夹
Command-Control-T 添加到边栏 (OS X Mavericks)
Command-Option-I 显示或隐藏“检查器”窗口
Command-Control-I 获得摘要信息
Command-Option-P 隐藏或显示路径栏
Command-Option-S 隐藏或显示边栏
Command-正斜线 (/) 隐藏或显示状态栏
Command-J 调出“显示”选项
Command-K 连接到服务器
Command-L 为所选项制作替身
Command-N 新建 Finder 窗口
Command-Shift-N 新建文件夹
Command-Option-N 新建智能文件夹
Command-O 打开所选项
Command-R 显示(替身的)原身
Command-T 在当前 Finder窗口中打开单个标签时显示或隐藏标签栏
Command-Shift-T 显示或隐藏 Finder 标签
Command-Option-T 在当前 Finder窗口中打开单个标签时显示或隐藏工具栏
Command-V 将您放在剪贴板上的文本副本粘贴到当前位置。
Command-Option-V 将您放在剪贴板上的文本从其原始位置移动到当前位置。
Command-Option-Y 查看选中文件的快速查看幻灯片。
Command-1 以图标显示
Command-2 以列表方式显示
Command-3 以分栏方式显示
Command-4 以 Cover Flow 方式显示(Mac OS X v10.5 或更高版本)
Command-逗号 (,) 打开 Finder 偏好设置
Command-左中括号 ([) 前往上一文件夹
Command-右中括号 (]) 前往下一文件夹
Command-Control-上箭头 在新窗口中打开包含当前文件夹的文件夹
Command-下箭头 打开高亮显示的项目
右箭头(以列表视图显示) 打开所选文件夹
左箭头(以列表视图显示) 关闭所选文件夹
Option-点按显示三角形 (以列表视图显示)打开所选文件夹内的所有文件夹
Option-连按 在单独窗口中打开文件夹,并关闭当前窗口
Command-连按 在单独标签或窗口中打开文件夹
Command-点按窗口标题 查看包含当前窗口的文件夹
Command-Delete 移至废纸篓
Command-Shift-Delete 清倒废纸篓
Command-Shift-Option-Delete 清倒废纸篓(不显示确认对话框)
空格键(或 Command-Y) 快速查看选中的文件
拖移时按 Command 键 将拖移的项目移至其他宗卷或位置(按住按键时指针会改变)
拖移时按 Option键 拷贝拖移的项目(按住按键时指针会改变)
拖移时按 Command-Option 组合键 对拖移的项目赋予别名(按住按键时指针会改变)
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