精华内容
下载资源
问答
  • 【mysql】mysql删除重复记录并且保留一条

    万次阅读 多人点赞 2018-09-03 21:10:13
    目录 、单个字段的操作 分组介绍: 1. 查询全部重复的数据: 2. 删除全部重复试题: ...4. 删除表中多余重复试题并且留1: a. 第种方法: b. ☆第二种方法(与上面查询的第二种方法对应,...

    目录

    一、单个字段的操作

    分组介绍:

    1. 查询全部重复的数据:

    2. 删除全部重复试题:

    3. 查询表中多余重复试题(根据depno来判断,除了rowid最小的一个)

    a. 第一种方法:

    b. 第二种方法:

    c. 补充第三种方法(根据评论区给的删除总结出来的):

    4. 删除表中多余重复试题并且只留1条:

    a. 第一种方法:

    b. ☆第二种方法(与上面查询的第二种方法对应,只是将select改为delete):

    c. 补充第三种方法(评论区推荐的一种方法):

    二、多个字段的操作:

    总结:


    最近在做题库系统,由于在题库中添加了重复的试题,所以需要查询出重复的试题,并且删除掉重复的试题只保留其中1条,以保证考试的时候抽不到重复的题。

    首先写了一个小的例子:

    一、单个字段的操作

    这是数据库中的表:

    分组介绍:

    Select 重复字段 From 表 Group By 重复字段 Having Count(*)>1

    查看是否有重复的数据:

    GROUP BY <列名序列>

    HAVING <组条件表达式>

    查询出:根据dname分组,同时满足having字句中组条件表达式(重复次数大于1)的那些组

    count(*)与count(1) 其实没有什么差别,用哪个都可以

    count(*)与count(列名)的区别:

        count(*)将返回表格中所有存在的行的总数包括值为null的行,然而count(列名)将返回表格中除去null以外的所有行的总数(有默认值的列也会被计入)

    1. 查询全部重复的数据:

    Select * From 表 Where 重复字段 In (Select 重复字段 From 表 Group By 重复字段 Having Count(*)>1)
    

    2. 删除全部重复试题:

    将上面的查询select改为delete(这样会出错的)

    DELETE
    FROM
    	dept
    WHERE
    	dname IN (
    		SELECT
    			dname
    		FROM
    			dept
    		GROUP BY
    			dname
    		HAVING
    			count(1) > 1
    	)

    会出现如下错误:[Err] 1093 - You can't specify target table 'dept' for update in FROM clause

    原因是:更新这个表的同时又查询了这个表,查询这个表的同时又去更新了这个表,可以理解为死锁。mysql不支持这种更新查询同一张表的操作

    解决办法:把要更新的几列数据查询出来做为一个第三方表,然后筛选更新。

     

    3. 查询表中多余重复试题(根据depno来判断,除了rowid最小的一个)

    a. 第一种方法:

    SELECT
    	*
    FROM
    	dept
    WHERE
    	dname IN (
    		SELECT
    			dname
    		FROM
    			dept
    		GROUP BY
    			dname
    		HAVING
    			COUNT(1) > 1
    	)
    AND deptno NOT IN (
    	SELECT
    		MIN(deptno)
    	FROM
    		dept
    	GROUP BY
    		dname
    	HAVING
    		COUNT(1) > 1
    )

    上面这种写法正确,但是查询的速度太慢,可以试一下下面这种方法:

    b. 第二种方法:

    根据dname分组,查找出deptno最小的。然后再查找deptno不包含刚才查出来的。这样就查询出了所有的重复数据(除了deptno最小的那行)

    SELECT *
    FROM
    	dept
    WHERE
    	deptno NOT IN (
    		SELECT
    			dt.minno
    		FROM
    			(
    				SELECT
    					MIN(deptno) AS minno
    				FROM
    					dept
    				GROUP BY
    					dname
    			) dt
    	)

    c. 补充第三种方法(根据评论区给的删除总结出来的):

    SELECT
    	* 
    FROM
    	table_name AS ta 
    WHERE
    	ta.唯一键 <> ( SELECT max( tb.唯一键 ) FROM table_name AS tb WHERE ta.判断重复的列 = tb.判断重复的列 );

     

    4. 删除表中多余重复试题并且只留1条:

    a. 第一种方法:

    DELETE
    FROM
    	dept
    WHERE
    	dname IN (
    		SELECT
    			t.dname
    		FROM
    			(
    				SELECT
    					dname
    				FROM
    					dept
    				GROUP BY
    					dname
    				HAVING
    					count(1) > 1
    			) t
    	)
    AND deptno NOT IN (
    SELECT
    	dt.mindeptno
    FROM
    	(
    		SELECT
    			min(deptno) AS mindeptno
    		FROM
    			dept
    		GROUP BY
    			dname
    		HAVING
    			count(1) > 1
    	) dt
    )

    b. ☆第二种方法(与上面查询的第二种方法对应,只是将select改为delete):

    DELETE
    FROM
    	dept
    WHERE
    	deptno NOT IN (
    		SELECT
    			dt.minno
    		FROM
    			(
    				SELECT
    					MIN(deptno) AS minno
    				FROM
    					dept
    				GROUP BY
    					dname
    			) dt
    	)

    c. 补充第三种方法(评论区推荐的一种方法):

    DELETE 
    FROM
    	table_name AS ta 
    WHERE
    	ta.唯一键 <> (
    SELECT
    	t.maxid 
    FROM
    	( SELECT max( tb.唯一键 ) AS maxid FROM table_name AS tb WHERE ta.判断重复的列 = tb.判断重复的列 ) t 
    	);

    二、多个字段的操作:

    单个字段的如果会了,多个字段也非常简单。就是将group by 的字段增加为你想要的即可。

    此处只写一个,其他方法请仿照一个字段的写即可。

    DELETE
    FROM
    	dept
    WHERE
    	(dname, db_source) IN (
    		SELECT
    			t.dname,
    			t.db_source
    		FROM
    			(
    				SELECT
    					dname,
    					db_source
    				FROM
    					dept
    				GROUP BY
    					dname,
    					db_source
    				HAVING
    					count(1) > 1
    			) t
    	)
    AND deptno NOT IN (
    	SELECT
    		dt.mindeptno
    	FROM
    		(
    			SELECT
    				min(deptno) AS mindeptno
    			FROM
    				dept
    			GROUP BY
    				dname,
    				db_source
    			HAVING
    				count(1) > 1
    		) dt
    )

    总结:

    其实上面的方法还有很多需要优化的地方,如果数据量太大的话,执行起来很慢,可以考虑加优化一下:

    • 在经常查询的字段上加上索引
    • 将*改为你需要查询出来的字段,不要全部查询出来
    • 小表驱动大表用IN,大表驱动小表用EXISTS。IN适合的情况是外表数据量小的情况,而不是外表数据大的情况,因为IN会遍历外表的全部数据,假设a表100条,b表10000条那么遍历次数就是100*10000次,而exists则是执行100次去判断a表中的数据是否在b表中存在,它只执行了a.length次数。至于哪一个效率高是要看情况的,因为in是在内存中比较的,而exists则是进行数据库查询操作的

     

                                                                                                本人小菜一枚,有什么写的不妥的地方,欢迎大家指教!

                                                                                                我会不定期的看评论,也会根据大家的指点来修改博客不妥的地方!

                                                                                                各位读者有什么好的方法,或者想法欢迎评论区留言。。。

    展开全文
  • 本文以个示例向大家讲解下如何实现如标题所示的情况,有此需求的朋友可以了解下 通常情况下,我们会使用以下SQL语句来更新字段值: 复制代码 代码如下: UPDATE mytable SET myfield='value' ...

    如果你想更新多行数据,并且每行记录的各字段值都是各不一样,你会怎么办呢?本文以一个示例向大家讲解下如何实现如标题所示的情况,有此需求的朋友可以了解下




    通常情况下,我们会使用以下SQL语句来更新字段值:

    复制代码 代码如下:

    UPDATE mytable SET myfield='value' WHERE other_field='other_value';

    但是,如果你想更新多行数据,并且每行记录的各字段值都是各不一样,你会怎么办呢?举个例子,我的博客有三个分类目录(免费资源、教程指南、橱窗展示),这些分类目录的信息存储在数据库表categories中,并且设置了显示顺序字段 display_order,每个分类占一行记录。如果我想重新编排这些分类目录的顺序,例如改成(教程指南、橱窗展示、免费资源),这时就需要更新categories表相应行的display_order字段,这就涉及到更新多行记录的问题了,刚开始你可能会想到使用循环执行多条UPDATE语句的方式,就像以下的php程序示例:
    复制代码 代码如下:

    foreach ($display_order as $id => $ordinal) {
    $sql="UPDATE categories SET display_order = $ordinal WHERE id = $id";
    mysql_query($sql);
    }

    这种方法并没有什么任何错误,并且代码简单易懂,但是在循环语句中执行了不止一次SQL查询,在做系统优化的时候,我们总是想尽可能的减少数据库查询的次数,以减少资源占用,同时可以提高系统速度。
    幸运的是,还有更好的解决方案,下面列举两种常用的方案只不过SQL语句稍微复杂点,但是只需执行一次查询即可,语法如下:

    •第一种:IF--THEN语句结合
    复制代码 代码如下:

    UPDATE mytable
    SET myfield = CASE other_field
    WHEN 1 THEN 'value'
    WHEN 2 THEN 'value'
    WHEN 3 THEN 'value'
    END
    WHERE id IN (1,2,3)

    回到我们刚才的分类目录的例子,我们可以使用以下SQL语句:
    复制代码 代码如下:

    UPDATE categories
    SET display_order = CASE id
    WHEN 1 THEN 3
    WHEN 2 THEN 4
    WHEN 3 THEN 5
    END,
    title = CASE id
    WHEN 1 THEN 'New Title 1'
    WHEN 2 THEN 'New Title 2'
    WHEN 3 THEN 'New Title 3'
    END
    WHERE id IN (1,2,3)

    以上方案大大减少了数据库的查询操作次数,大大节约了系统资源,但是该怎样与我们的编程语言结合起来呢?我们还是用刚才分类目录的例子,以下是php的程序示例:
    复制代码 代码如下:

    $display_order = array(
    1 => 4,
    2 => 1,
    3 => 2,
    4 => 3,
    5 => 9,
    6 => 5,
    7 => 8,
    8 => 9
    );
    $ids = implode(',', array_keys($display_order));
    $sql = "UPDATE categories SET display_order = CASE id ";
    foreach ($display_order as $id => $ordinal) {
    $sql .= sprintf("WHEN %d THEN %d ", $id, $ordinal); // 拼接SQL语句
    }
    $sql .= "END WHERE id IN ($ids)";
    echo $sql;
    mysql_query($sql);

    在这个例子中总共更新了8行数据,但是只执行了一次数据库查询,相比于循环执行8次UPDATE语句,以上例子所节约的时间可以说是微不足道的。但是想想,当你需要更新10,0000或者更多行记录时,你会发现这其中的好处!唯一要注意的问题是SQL语句的长度,需要考虑程序运行环境所支持的字符串长度,我目前获得的数据:SQL语句长度达到1,000,960在php中仍然可以顺利执行,我查询了php文档并没有发现明确规定字符串最大长度。

    •第二种INSERT方式
    MySql中INSERT语法具有一个条件DUPLICATE KEY UPDATE,这个语法和适合用在需要判断记录是否存在,不存在则插入存在则更新的记录。
    基于上面这种情况,针对更新记录,仍然使用insert语句,不过限制主键重复时,更新字段。如下:
    复制代码 代码如下:

    INSERT INTO t_member (id, name, email) VALUES
    (1, 'nick', 'nick@126.com'),
    (4, 'angel','angel@163.com'),
    (7, 'brank','ba198@126.com')
    ON DUPLICATE KEY UPDATE name=VALUES(name), email=VALUES(email);

    注意:ON DUPLICATE KEY UPDATE只是MySQL的特有语法,并不是SQL标准语法! 
    展开全文
  • 没错,我目前打算写本关于Unity Shader的书。出书的目的有下面几个: 总结我接触Unity Shader以来的历程,给其他人个借鉴。我非常明白学Shader的艰难,在群里也见了很多人提出的问题。我觉得学习Shader还是件...


    写在前面



    感谢所有点进来看的朋友。没错,我目前打算写一本关于Unity Shader的书。

    出书的目的有下面几个:

    1. 总结我接触Unity Shader以来的历程,给其他人一个借鉴。我非常明白学Shader的艰难,在群里也见了很多人提出的问题。我觉得学习Shader还是一件有规律可循的事情,但问题是中文资料难觅,而大家又不愿意去看英文。。。这对我有什么好处呢?强迫我对知识进行梳理,对细节问题把握更清楚。

    2. 第二个原因你懂的。

    关于本书的定位问题:

    1. 面向Unity Shader初学者,但要:

      1. 有一定的编程经历,不然我说:在脚本里写一个函数XXX,您问我,脚本是啥?我:……。
      2. 希望您还记得初中高中的基本数学。起码能把数算清楚。我明白很多人早就把矩阵这些稍微复杂一点的数学还给了大学老师,所以我会单独在一个章节里介绍。
      3. 希望您有一定的耐心。为什么你老是觉得看不懂、学不会Shader,可以反思下自己是不是太急躁了,想要今天看一下明天就会。放弃吧,这是不可能的。

      我写这本书的一个目标是,希望帮助初学者把基础打牢,没有基础任何上层建筑都是不可靠的。

    2. 我不是在写一本特效大全,所以你如果想要看到各种酷炫狂霸拽的特效,抱歉,这本书里几乎没有。这跟上一点有很大关系,仅靠一本书,我可以肯定一个初学者没有办法成为一个“Shader大神”。我希望所有读过这本书的人可以真正明白shader是个什么东西,而不是说:“哦,shader嘛,就是在Unity里右键Create->Shader得到的那个东西嘛”。关于特效大全的问题,如果将来我有十足的经验和资格了,可能会真的写一本,哈哈哈


      写书是件很不容易的事情,希望我可以把它做好。

    2015.12.21更新:关于什么时候出版


    不少朋友留言或者发邮件问我什么时候出版,我比你们更着急呀……不过编辑说还在修改和排版,大概出版时间会在明年一月份(希望不会延期吧)。谢谢大家帮我起名字!我把一些大家起得名字拿给编辑看,以及和朋友讨论,最后还是暂定为《Unity Shader入门精要》。难听么?别打击我……下面有朋友起了很多萌萌哒的名字,利用下程序媛的身份,不过吧,感觉这个因人而异,说不定有人就不喜欢程序媛写的书呢……所以最后还是挑了这个比较严肃的名字,嗯。

    书的封面我也找万能的设计师兰朋友设计啦~

    这里写图片描述

    还没出版所以打打水印。当然了,编辑只是同意用了,但是应该还会修改吧。不知道大家觉得封面怎么样……我是觉得萌萌哒,哈哈。


    2016.1.29更新


    不好意思地告诉大家,书籍出版时间推迟了。编辑说由于北京雾霾,所以印刷厂没法大量印刷书籍,造成很多书籍堆压,因此就要到年后。承蒙大家厚爱,一直关心这本书的出版,很感动。有朋友说隔几天就来看一眼我又开心又觉得有点愧疚。如果你觉得总是来这里看很麻烦的话可以给我发个邮件:lelefeng1992 # gmail DOT com,我会把你的邮箱加到列表里,等出版后会给您发邮件通知

    再次感谢大家的支持,我和你们一样,希望早日看到书出版!



    2016.03.04更新:我的天哪到底什么时候出版!


    由于大家的连环夺命催,我也变成了催债婆,隔三差五就问编辑到底啥时候能看到书。呐,编辑说了,”就像不敢催作者尽快交书稿,因为怕作者赶时间写不好一样,文字编辑也不敢催他们,怕弄不好了“。编辑给了我他们修改的照片,让我安抚下我们的内心,”看吧,这么多错误要改,以为很容易的吗?!“(这话是我说的……)编辑的原话是说,让大家看看,”你、我们、编辑都在认真工作尽量把书弄好。“恩。

    这里写图片描述这里写图片描述这里写图片描述这里写图片描述

    我又问了下什么时候可以出版,编辑说是3月底,我说相信编辑。好了,事情的经过就是这样,我们一起再等等吧。再次谢谢各位的关注和支持!我很感动,真的。



    2016.05.05更新:讲真,到底什么时候出版



    时隔两个月我终于又更新了……其中的艰辛我就不说了,总之结果就是目前修改都修改完了,编辑说就等着印刷了,上市的话会在5月中旬,并承诺“这一次不辜负你和读者了”。我们拭目以待吧。

    经过多次修改(其实一直在修改文字,改错字,哎,啥也不说了),封面也终于出来了:

    这里写图片描述

    封面是兰盆友设计的草稿 :) 还要多谢雨松前辈和风宇冲前辈写的序!

    其实早在一个月前,我就把项目源码和书里所有的插图彩色版放到了网上,有需要的朋友可以现在就去查看了:

    关于彩色版的问题,这次还是会印刷成黑白的,主要还是成本考虑,因为不知道这书销量怎么样,定价高了担心销量会受影响。所以目前这书的定价应该是69元,网上一打折应该就是50块左右。不过我已经把彩图都放到网上了,就是需要读者麻烦点自己去根据图片编号来查看相应彩图了。

    希望这是最后一次更新了,下一次直接开新的文章说上市啦~




    2016.05.19更新:出版日期



    大家好,之前说的五月中旬不出意外地又延期了,不过好消息是五月末六月初一定会上市的!~书目前正在印刷过程中,人民邮电出版社在他们的官方网站上放出了预售链接:http://www.epubit.com.cn/book/details/4576。定价是69元,打折一下大概是53元,不过也是预售,目前还没有印刷好,预计上市时间是5月28日。这个网站会比京东、亚马逊等网站到货早一点,但大家也不用急于在这上面购买,我自己也还没拿到样书……

    等到京东、亚马逊等网站正式上市的时候,我会再更新一篇文章。这是本篇文章最后一次更新,在此真心真心感谢大家的支持,希望不负各位的厚望 :)


    整体结构



    我把这本书分为五大篇章:

    • 基础篇:这是很重要的一章,主要是为了初学者普及基本的理论知识,以及所需的数学基础。我明白很多人看不懂网上的一些材料,我尽量讲得通俗。

    • Shader初级篇:从最简单的shader开始,讲解shader中基础的光照模型、纹理、和透明效果等。同时,还会介绍一些shader的Debug技巧、shader里常见报错信息。

    • Shader中级篇:这是进阶篇章,将讲解更加复杂的光照、高级纹理、以及如何用shader实现动画等一系列进阶内容;

    • Shader高级篇:则涵盖了一些shader的高级用法,如使用缓冲区、实现屏幕特效、非真实感渲染等,同时,还会介绍一些优化技巧;

    • 扩展篇:将会涵盖一些Unity Surface Shader背后的机制,还会针对Unity 5.0+版本中的一些新的特性进行简要分析。最后,希望向大家介绍一点学习shader的经验和资源。

    目前目录已经初步定型,把目录记录在这里,但我会不断更新。



    如果您对该书的目录和内容有任何意见和建议都可以在下方留言。如果您没有CSDN账号,也可以通过发邮件来告诉我:lelefeng1992 # gmail DOT com。我会根据您的意见对目录和内容做出一定的更改。



    目录(已完整)



    * 前言
    * 这本书讲些什么
    * 读这本书之前你需要哪些知识
    * 谁适合读这本书
    * 谁暂时还不适合读这本书
    * 约定
    * 读者反馈
    * 本书源码

    第1部分 基础篇

    • 第1章 欢迎来到Shader的世界

      • 1.1 程序员的三大浪漫:为什么要学习Shader
      • 1.2 这不是程序员一个人的战斗
      • 1.3 世界这么大
    • 第2章 渲染流水线

      • 2.1 综述
        • 2.1.1 什么是流水线
        • 2.1.2 什么是渲染流水线
      • 2.2 CPU和GPU的通信
        • 2.2.1 把数据加载到显存中
        • 2.2.2 设置渲染状态
        • 2.2.3 调用Draw Call
      • 2.3 GPU流水线
        • 2.3.1 概述
        • 2.3.2 顶点着色器
        • 2.3.3 裁剪
        • 2.3.4 屏幕映射
        • 2.3.5 三角形设置
        • 2.3.6 三角形遍历
        • 2.3.7 片元着色器
        • 2.3.8 逐片元操作
        • 2.3.9 总结
      • 2.4 一些容易困惑的地方
        • 2.4.1 什么是OpenGL/DirectX
        • 2.4.2 什么是HLSL、GLSL、CG
        • 2.4.3 什么是Draw Call
        • 2.4.4 什么是固定渲染管线(Fixed-Function Pipeline)
      • 2.5 那么,你明白什么是Shader了吗
      • 扩展阅读
    • 第3章 Unity Shader基础

      • 3.1 Unity Shader概述
        • 3.1.1 一对好兄弟:材质(Material)和Unity Shader
        • 3.1.2 Unity中的材质
        • 3.1.3 Unity中的Shader
      • 3.2 Unity Shader的基础:ShaderLab
        • 3.2.1 什么是ShaderLab
      • 3.3 Unity Shader的结构
        • 3.3.1 给我们的Shader起个名字:Shader
        • 3.3.2 材质和Unity Shader的桥梁:Properties
        • 3.3.3 重量级成员:SubShader
        • 3.3.4 留一条后路:Fallback
        • 3.3.5 ShaderLab还有其他的语义吗
      • 3.4 Unity Shader的形式
        • 3.4.1 Unity的宠儿:Surface Shader
        • 3.4.2 最聪明的孩子:Vertex/Fragment Shader
        • 3.4.3 抛弃的角落:Fixed Function Shader
        • 3.4.4 那么,要选择哪种Unity Shader形式
      • 3.5 本书使用的Unity Shader形式
      • 3.6 答疑解惑
        • 3.6.1 Unity Shader != 真正的Shader
        • 3.6.2 Unity Shader和CG/HLSL之间的关系
        • 3.6.3 我可以使用GLSL来写吗
      • 扩展阅读
    • 第4章 学习Shader所需的数学基础

      • 4.1 背景:农场游戏
      • 4.2 笛卡尔坐标系
        • 4.2.1 二维笛卡尔坐标系
        • 4.2.2 三维笛卡尔坐标系
        • 4.2.3 左手坐标系和右手坐标系
        • 4.2.4 Unity使用的坐标系
        • 4.2.5 练习题
      • 4.3 点和矢量
        • 4.3.1 点和矢量的区别
        • 4.3.2 矢量运算
          • 4.3.2.1 矢量和标量乘法/除法
          • 4.3.2.2 矢量的加法和减法
          • 4.3.2.3 矢量的模
          • 4.3.2.4 单位矢量
          • 4.3.2.5 矢量的点积
          • 4.3.2.6 矢量的叉积
        • 4.3.3 练习题
      • 4.4 矩阵
        • 4.4.1 矩阵的定义
        • 4.4.2 和矢量联系起来
        • 4.4.3 矩阵运算
          • 4.4.3.1 矩阵和标量的乘法
          • 4.4.3.2 矩阵和矩阵的乘法
        • 4.4.4 特殊的矩阵
          • 4.4.4.1 方块矩阵
          • 4.4.4.2 单位矩阵
          • 4.4.4.3 转置矩阵
          • 4.4.4.4 逆矩阵
          • 4.4.4.5 正交矩阵
        • 4.4.5 行矩阵还是列矩阵
        • 4.4.6 练习题
      • 4.5 矩阵的几何意义:变换
        • 4.5.1 齐次坐标
        • 4.5.2 分解基础变换矩阵
        • 4.5.3 平移矩阵
        • 4.5.4 缩放矩阵
        • 4.5.5 旋转矩阵
        • 4.5.6 组合变换
        • 4.5.7 练习题
      • 4.6 坐标空间
        • 4.6.1 为什么要使用这么多不同的坐标空间
        • 4.6.2 坐标空间的变换
        • 4.6.3 顶点的坐标空间变换过程
          • 4.6.3.1 案例
        • 4.6.4 模型空间
          • 4.6.4.1 案例
        • 4.6.5 世界空间
          • 4.6.5.1 案例
        • 4.6.6 观察空间
          • 4.6.6.1 案例
        • 4.6.7 裁剪空间
          • 4.6.7.1 透视投影
          • 4.6.7.2 正交投影
          • 4.6.7.3 案例
        • 4.6.8 屏幕空间
          • 4.6.8.1 案例
        • 4.6.9 总结
      • 4.7 法线变换
      • 4.8 Unity Shader中的内置变量(数学篇)
      • 4.9 答疑解惑
        • 4.9.1 使用3 x 3还是4 x 4的变换矩阵
        • 4.9.2 Cg中的矢量和矩阵类型
        • 4.9.3 Unity中的屏幕坐标:ComputeScreenPos/VPOS/WPOS
      • 练习题答案
      • 扩展阅读

    第2部分初级篇

    • 第5章 开始Unity Shader学习之旅

      • 5.1 本书使用的软件和环境
      • 5.2 一个最简单的Vertex/Fragment Shader
        • 5.2.1 Vertex/Fragment Shader的基本结构
        • 5.2.2 模型数据从哪来
        • 5.2.3 顶点着色器和片元着色器之间如何通信
        • 5.2.4 如何使用属性
      • 5.3 强大的援手:Unity提供的内置文件和变量
        • 5.3.1 内置的包含文件
        • 5.3.2 内置的变量
      • 5.4 Unity提供的Cg/HLSL语义
        • 5.4.1 什么是语义
        • 5.4.2 Unity支持的语义
        • 5.4.3 如何定义复杂的变量类型
      • 5.5 程序员的烦恼:Deeeeebug
        • 5.5.1 使用假彩色图像
        • 5.5.2 利用神器:Visual Studio
      • 5.6 小心:渲染平台的差异
        • 5.6.1 渲染纹理的坐标差异
        • 5.6.2 Shader的语法差异
        • 5.6.3 Shader的语义差异
        • 5.6.4 其他平台差异
      • 5.7 Shader整洁之道
        • 5.7.1 float、half还是fixed
        • 5.7.2 规范语法
        • 5.7.3 避免不必要的计算
        • 5.7.4 慎用分支和循环语句
        • 5.7.5 不要除以0
      • 扩展阅读
    • 第6章 Unity中的基础光照

      • 6.1 我们是如何看到这个世界的
        • 6.1.1 光源
        • 6.1.2 吸收和散射
        • 6.1.3 着色
        • 6.1.4 BRDF光照模型
      • 6.2 标准光照模型
        • 6.2.1 环境光
        • 6.2.2 自发光
        • 6.2.3 漫反射
        • 6.2.4 高光反射
        • 6.2.5 逐像素还是逐顶点
        • 6.2.6 总结
      • 6.3 环境光和自发光
      • 6.4 漫反射光照模型
        • 6.4.1 实践:逐顶点光照
        • 6.4.2 实践:逐像素光照
        • 6.4.3 改善技巧:半兰伯特模型
      • 6.5 高光反射光照模型
        • 6.5.1 实践:逐顶点光照
        • 6.5.2 实践:逐像素光照
        • 6.5.3 Blinn-Phong模型
      • 6.6 召唤神龙:使用Unity内置的函数
        • 6.6.1 使用内置函数改写Unity Shader
    • 第7章 基础纹理

      • 7.1 单张纹理
        • 7.1.1 实践
        • 7.1.2 解释
        • 7.1.3 纹理的属性
      • 7.2 凹凸映射
        • 7.2.1 高度纹理
        • 7.2.2 法线纹理
        • 7.2.3 实践
        • 7.2.4 解释
        • 7.2.5 Unity中的法线纹理类型
      • 7.3 渐变纹理
        • 7.3.1 实践
        • 7.3.2 解释
      • 7.4 遮罩纹理
        • 7.4.1 实践
        • 7.4.2 解释
        • 7.4.3 其他遮罩纹理
    • 第8章 透明效果

      • 8.1 为什么渲染顺序很重要
      • 8.2 Unity Shader的渲染顺序
      • 8.3 透明度测试
        • 8.3.1 实践
        • 8.3.2 解释
      • 8.4 透明度混合
        • 8.4.1 实践
        • 8.4.2 解释
      • 8.5 开启深度写入的半透明效果
        • 8.5.1 实践
        • 8.5.2 解释
      • 8.6 ShaderLab的混合命令
        • 8.6.1 混合等式和参数
        • 8.6.2 混合操作
        • 8.6.3 常见的混合类型

    第3部分 中级篇

    • 第9章 更复杂的光照

      • 9.1 Unity的渲染路径
        • 9.1.1 前向渲染路径
          • 9.1.1.1 前向渲染路径的原理
          • 9.1.1.2 Unity中的前向渲染
          • 9.1.1.3 内置的光照变量和函数
        • 9.1.2 顶点照明渲染路径
          • 9.1.2.1 Unity中的顶点照明渲染
          • 9.1.2.1 可访问的内置变量和函数
        • 9.1.3 延迟渲染路径
          • 9.1.3.1 延迟渲染的原理
          • 9.1.3.2 Unity中的延迟渲染
          • 9.1.2.3 可访问的内置变量和函数
        • 9.1.4 选择哪种渲染路径
      • 9.2 Unity的光源类型
        • 9.2.1 光源类型有什么影响
          • 9.2.1.1 平行光
          • 9.2.1.2 点光源
          • 9.2.1.3 聚光灯
        • 9.2.2 在前向渲染中处理不同的光源类型
          • 9.2.2.1 实践
          • 9.2.2.2 解释
          • 9.2.2.3 实验:Base Pass和Additional Pass的调用
      • 9.3 Unity的光照衰减
        • 9.3.1 用于光照衰减的纹理
        • 9.3.2 使用数学公式计算衰减
      • 9.4 Unity的阴影
        • 9.4.1 阴影是如何实现的
        • 9.4.2 不透明物体的阴影
          • 9.4.2.1 让物体投射阴影
          • 9.4.2.2 让物体接收阴影
        • 9.4.3 使用帧调试器查看阴影绘制过程
        • 9.4.4 统一管理光照衰减和阴影
        • 9.4.5 使用透明度测试的物体的阴影
    • 第10章 高级纹理

      • 10.1 立方体纹理
        • 10.1.1 天空盒子
        • 10.1.2 创建用于环境映射的立方体纹理
        • 10.1.3 反射
        • 10.1.4 折射
        • 10.1.5 菲涅尔反射
      • 10.2 渲染纹理
        • 10.2.1 镜子效果
        • 10.2.2 玻璃效果
      • 10.3 程序纹理
        • 10.3.1 在Unity中实现简单的程序纹理
        • 10.3.2 Unity的程序材质
    • 第11章 让画面动起来

      • 11.1 Unity Shader中的内置变量(时间篇)
      • 11.2 纹理动画
        • 11.2.1 序列帧动画
        • 11.2.2 滚动的背景
      • 11.3 顶点动画
        • 11.3.1 流动的河流
        • 11.3.2 广告牌
        • 11.3.3 注意事项

    第4部分 Shader高级篇

    • 第12章 屏幕后处理效果

      • 12.1 建立一个基本的屏幕后处理脚本系统
      • 12.2 调整亮度、饱和度和对比度
      • 12.3 边缘检测
        • 12.3.1 什么是卷积
        • 12.3.2 常见的边缘检测算子
        • 12.3.3 实现
      • 12.4 高斯模糊
        • 12.4.1 高斯滤波
        • 12.4.2 实现
      • 12.5 Bloom效果
      • 12.6 运动模糊
      • 12.7 扩展阅读
    • 第13章 使用深度和法线纹理

      • 13.1 获取深度和法线纹理
        • 13.1.1 背后的原理
        • 13.1.2 如何获取
        • 13.1.3 查看深度和法线纹理
      • 13.2 再谈运动模糊
      • 13.3 全局雾效
        • 13.3.1 重建世界坐标
        • 13.3.2 雾的计算
        • 13.3.3 实现
      • 13.4 再谈边缘检测
      • 13.5 扩展阅读
    • 第14章 非真实感渲染

      • 14.1 卡通风格的渲染
        • 14.1.1 渲染轮廓线
        • 14.1.2 添加高光
        • 14.1.3 实现
      • 14.2 素描风格的渲染
      • 14.3 扩展阅读
      • 14.4 参考文献
    • 第15章 使用噪声

      • 15.1 消融效果
      • 15.2 水波效果
      • 15.3 再谈全局雾效
      • 15.4 扩展阅读
      • 15.5 参考文献
    • 第16章 Unity中的渲染优化技术

      • 16.1 移动平台的特点
      • 16.2 影响性能的因素
      • 16.3 Unity中的渲染分析工具
        • 16.3.1 认识Unity 5的渲染统计窗口
        • 16.3.2 性能分析器的渲染区域
        • 16.3.3 再谈帧调试器
        • 16.3.4 其他性能分析工具
      • 16.4 减少Draw Call数目
        • 16.4.1 动态批处理
        • 16.4.2 静态批处理
        • 16.4.3 共享材质
        • 16.4.4 批处理的注意事项
      • 16.5 减少需要处理的顶点数目
        • 16.5.1 优化几何体
        • 16.5.2 模型的LOD技术
        • 16.5.3 遮挡剔除技术
      • 16.6 减少需要处理的片元数目
        • 16.6.1 控制绘制顺序
        • 16.6.2 时刻警惕半透明物体
        • 16.6.3 减少实时光照
      • 16.7 节省带宽
        • 16.7.1 减少纹理大小
        • 16.7.2 利用分辨率缩放
      • 16.8 减少计算复杂度
        • 16.8.1 Shader的LOD技术
        • 16.8.2 代码方面的优化
        • 16.8.3 根据硬件条件进行缩放
      • 16.9 扩展阅读

    第5部分 扩展篇

    • 第17章 Surface Shader探秘

      • 17.1 一个例子
      • 17.2 编译指令
        • 17.2.1 表面函数
        • 17.2.2 光照函数
        • 17.2.3 其他可选参数
      • 17.3 两个结构体
        • 17.3.1 数据来源:Input结构体
        • 17.3.2 表面属性:SurfaceOutput结构体
      • 17.4 Unity背后做了什么
      • 17.5 实例分析
      • 17.6 Surface Shader的缺点
    • 第18章 基于物理的渲染

      • 18.1 PBS的理论和数学基础
        • 18.1.1 光是什么
        • 18.1.2 BRDF
        • 18.1.3 漫反射项
        • 18.1.4 高光反射项
        • 18.1.5 Unity中的PBS实现
      • 18.2 Unity 5的Standard Shader
        • 18.2.1 它们是如何实现的
        • 18.2.2 如何使用Standard Shader
      • 18.3 一个更加复杂的例子
        • 18.3.1 设置光照环境
        • 18.3.2 放置反射探针
        • 18.3.3 调整材质
        • 18.3.4 线性空间
      • 18.4 答疑解惑
        • 18.4.1 什么是全局光照
        • 18.4.2 什么是伽马校正
        • 18.4.3 什么是HDR
        • 18.4.4 那么,PBS适合什么样的游戏
      • 18.5 扩展阅读
      • 参考文献
    • 第19章 Unity 5更新了什么

      • 19.1 场景“更亮了”
      • 19.2 表面着色器更容易“报错了”
      • 19.3 当家做主:自己控制非统一缩放的网格
      • 19.4 固定管线着色器逐渐退出舞台
    • 第20章 还有更多内容吗

      • 20.1 如果你想深入了解渲染的话
      • 20.2 世界那么大
      • 参考文献


    2015.06.28更新


    这几天在写数学的部分,早就料到数学是最难讲的一部分,尤其是矩阵。我和很多人一样,对矩阵这个家伙简直是”深恶痛绝“,看到它就想躲过去。无奈,shader里面要时常跟它打交道,那么,就勇敢地面对它吧!

    我很明白,为什么我们会这么”讨厌“矩阵。如果说矢量这种我们还可以通过可视化的方法来直观地理解,那么,矩阵,这个放在一个小方框里的东西,就很难用画的方式把它画出来。而我们人的大脑又是很懒惰的(恩,我只能为我的大脑代言),没图你说个XXX!我才懒得记!

    实际上,我一直对数学怀抱一种敬畏的心态。世界上有很多的数学家同时也是哲学家、心理学家,感觉数学对理解这个世界都有非常重要的意义,而且那些数学家的生平都很有意思,让人敬佩。能够将其一生都贡献给数学的人都很伟大的,那些创造矩阵、空间、矢量这些的人是多么伟大,怎么就会想到用这样一种方式来描述这种现象呢?这真的是件很神奇的事情。而且,你会发现,怎么这样算就可以表示出这种意思呢,明明看起来没有任何关系啊!这种巧合真的是让人感叹数学的伟大。

    好了,不再歪歪……回到真实的世界……在写的过程中,我会尽量用通俗、幽默、有图示的方式来讲这一章,效果怎么样,我也很忐忑,会不会反映说看不懂?现在一切都不得而知……

    一个有趣的事情是,在讲左右手坐标系和左右手法则的时候,我拿自己的手做了模型:

    这里写图片描述


    哈,这个黄色的手的确是我的手,然后用Photoshop处理了一下。看起来还挺像那么回事的?谁敢说我手胖我跟谁急!

    这几天一直在画图、看书、写文字、写公式(天哪,虽然用Markdown写公式已经很方便了,但一天要写那么多公式也真的是……)、算题,希望最后的结果是好的。加油吧!


    2015.07.10更新

    写了两个多星期,把数学一章的草稿基本完成了。今天更新了第2、3、4章的目录,有兴趣的可以看一下,欢迎提出各种意见和建议。

    数学篇是我最想好好写的一篇(当然啦,其他章我也会好好写。。。)。数学之所以难学,一部分是因为它的抽象性,没办法,如果我们想要把一些规律从生活中提取出来,就必然要涉及到各种数学符号,这就要用到抽象。我用了很多图和案例来尽量让这个过程更加形象易懂,也使用了一些类似对话的方式,来解释一些常见的疑惑。

    目前,本书的第一篇——基础篇基本成型。基础篇里每一章都有个小节叫做答疑解惑,意在总结一些常见的疑惑点,如果读者除了我上面写到的几点外还有其他的困惑,可以给我留言。我会视情况添加到这一章节。

    除此之外,在数学一章里我添加了练习题的部分。其实我是有犹豫的,觉得可能大家都会跳过去,那不是白写了。。。之所以要设置这个练习题的部分,一方面的确是希望读者可以通过这些练习真的拿笔算一下,说真的,数学你不多算真的永远学不会。另一方面,是想把一些容易混淆的点通过练习题的方式提出来,让读者自己算一下加深理解。因为如果要把这些混淆点都写进书里,思路上会比较乱。希望能起到比较好的效果吧。。。

    下面就会真正开始Unity Shader的部分了。加油!


    2015.07.29更新

    放假了大部分时间都拿来看资料、学习、写书了。半个多月写出了基本篇的草稿,不知道是快还是慢?我自信自己写的很详细了,比如第5章介绍了语义,第6章详细介绍了基本光照模型,第7章写到凹凸映射的时候也花了很大篇幅介绍实现的原理和细节,包括高度图,第8章的透明效果先介绍了渲染队列,我自己认为这个很重要的,应该在学习怎么实现透明之前就让读者知道渲染队列对透明来说是多么的重要。我觉得现在的安排对初学者足够友好了,当然写后面内容的时候可能还会对前面的内容进行改动,例如现在想在第4章数学里加一个在Unity脚本里的矩阵运算,但这本书是讲shader的,不知道加进去合不合适,但它的确是个容易出错的地方。

    每次讲到新的内容时,我都尽量用图示来解释,每一幅图都是在OmniGraffle里认真做的,希望以后看到的人能get到我的意思。写书写太多感觉写博客都语无伦次了。。。

    最近QQ群、私信和留言经常有人问题一些问题,我在这里统一回答一下。回答几个问题

    1. 这书什么时候出版?

      大家也看到了我的更新速度,目前写的了第8章(第一章介绍还没写),初步定的是19章,也就是说写了三分之一了,我现在大概花了一个多月,但是写书的确花费了很多时间,写完基本篇之后可能会放慢一下速度。总体来讲,我估测下大概还要三四个月的时间才能写完,因此出版的话最快年底,不然就是明年年初了。有一些人说太晚了,相信我,我比任何人都想让它赶紧出版,但是我不会影分身……好羡慕鸣人。

    2. 能不能增加些更高难度的技术?

      一些童鞋大概看了前几章目录后觉得内容比较简单。怎么说呢,这本书的定位是面向初学者,因此肯定会是由易到难的,但我自信的是,即便是简单的内容我也写的很详细,很多很小的点也都写到了,很多地方都是其他资料里一带而过,而又很迷惑的点。如果是没有好好学过shader的,就算现在已经可以熟练写一些了我觉得这本书也是有用的。

      更重要的是,我不想把它写成一本百科全书,一来我自己的确经验不够,写不来大全,二来我觉得一本大全的书肯定写不精、写不细,到头来又说看不懂怎么办?三来我觉得写shader是一个师傅领进门修行靠个人的活,一旦你了解了它的工作流程和基本思路,剩下的就是经验的积累,你看得写、写得多自然就厉害了,这不是一本基础书就可以让你做到的。

      当然,我的确会写一些复杂的技术,这是高级篇和扩展篇的工作。如果你觉得有一些常用的复杂一些的技术想要在这本书里看到,可以告诉我。

    3. 是彩色书还是黑白书?

      我自己当然希望是彩色书,一本讲画面效果的书竟然是黑白的那太遗憾了。不过编辑告诉我,彩色印刷会提高很多成本,那销量就会下降。我能够理解,但现在还没有一个定论,等写完之后会尽量争取。不过我也很好奇,大家觉得这样一本几百页的全彩书,你觉得多少价钱比较合适?

    2015.09.04更新


    断断续续把中级篇的草稿完成了。越往后面写感觉内容的安排越费劲,一些内容不知道把它们归入到哪一章更加合适,放的早了一些内容没讲担心读者看不明白,放的晚了又觉得内容不足单独成章。高级篇想必也会这样。目录还在不断调整中……

    写第9章光照简直是除数学篇外最痛苦的一章,想要讲明白非常难啊,不管怎样,目前的内容我尽力了,希望可以有好的效果。因为内容多而且杂,所以这一章不知不觉就写了四万字,也是目前字数最多的章节了。即便这样,仍然对一些内容“念念不忘”,例如菲尼尔光照、边缘光照等,不知道以后会不会加入进去。

    话说,写书的时候发现一个不错的免费纹理网站——http://opengameart.org/,写书的时候有一些纹理是从这里找到的,在这里也推荐给大家。当然,也有自己画的一些纹理。之前做游戏的时候做了一个2D水面,这次把它的实现也添加到了书里面。

    这里写图片描述

    呼,还有两大篇整体草稿就完成了。有些内容想偷点懒,使用点博客里写过的。。。9月估计要赶论文,进度会更慢。预计完成大概要11月或者12月了,希望大家可以耐心等待。我会加油的。

    2015.10.20更新

    恩,好久没更新了。由于9月份一直在弄别的事情所以写书的进程有些滞缓了,让大家久等了!不过还好,赶在11月之前把高级篇的草稿部分写完了,希望大家看了目录能够满意现在的内容。

    第12章讲屏幕特效,好吧,我承认我原来没想写这么多的,因为我一开始就说过这不是一本特效大全。不过写着写着,就觉得,恩,高斯模糊很重要,不能删,恩,边缘检测很重要,因为可以和后面联系在一起,恩,这样运动模糊也不能删了(后面也有联系)。所以写着写着就写了很多,不过希望大家看了书可以对这些屏幕特效有所了解,知道它们实现的基本原理(其实本质上都差不多),这样在实现更复杂的屏幕特效时也会有头绪了。第13章讲深度和法线缓存。其实好像移动平台上用的比较少?不过我觉得这张内容非常适合扩展视野,让大家知道原来这些纹理还可以这么用,里面一些内容,比如运动模糊和全局雾效参考了GPU Gems里面的文章,其实GPU Gems也并没有那么复杂。第14章讲了非真实感渲染,这章并不是重点,主要也是为了扩展视野,我选了最流行的卡通风格和非常出名的素描风格来做个例子。第15章讲了噪声在shader中的应用,噪声的应用实在太广了。。。第16章是许多人要求的优化,恩,有四五个童鞋都联系我说希望学习一些优化,如你们所愿:)。这章的内容参考了之前我的一篇博客,不过当然不是原封不动啦。。。内容更详细了,并针对Unity 5做了一些调整和变化,希望对大家有所启发。高级篇的一个主要目的是为了开阔视野,了解更多技术,因此每一章后面都有扩展阅读部分,给出了我能找到的所有我认为非常好的资料,能列在这部分的资料,我都强烈建议读者去读一下,相信你一定会有非常大的收获。

    好啦,最后放一些高级篇里实现的效果,欢迎大家提出意见和建议。

    这里写图片描述

    这里写图片描述

    这里写图片描述

    还有最后一篇扩展篇,计划讲一些关于Unity 5的PBR和类似于ShaderToy这样的内容,你怎么看?

    恩,一直有人问我什么时候出版,具体时间我真不知道。写完最后一篇大概11月初,然后我还要重新读一遍所有内容,做些调整和修改。这大概也要花一个月吧,也就是12月了。而且可能还有实验室的事情要做,因此出版大概要明天年初了。希望大家能再等一下。不过,真的很感谢一直支持我的各位,说实话写到现在的确有些到了倦怠期,不过因为有很多支持和鼓励的声音给了很多新的动力,谢谢大家。还是希望大家如果对和书有关的任何建议都可以联系我,不胜感激:)


    2015.11.09更新

    呜呼,不敢相信自己的速度,我竟然在11月赶出来了……截止到今天,书里面全部的20章内容就都完成了,上周已经对所有章节进行了我这方面的修改,然后交给编辑啦~我已经竭尽全力了,希望会有好的结果!

    • 关于什么时候出版

      编辑说大概还要一个多月吧,看我的内容需要多长时间排版,我会在博客里实时更新的(可能会开另一篇文章了吧)!

    • 关于封面和书名

      恩,其实之前给出版社写表格的时候填了个名字,《Unity Shader入门金典》,是不是觉得挺难听的……如果你有更好的名字一定要告诉我,如果最后使用了的话一定免费赠书

      封面的话,编辑说我可以提出自己的意见。我比较想用Shadertoy创始人iq的一些作品(http://www.iquilezles.org/www/articles/raymarchingdf/raymarchingdf.htm),比如下面这些(啊啊啊iq是我的偶像…):

      这里写图片描述

      这里写图片描述

      这些效果只使用了一个pixel shader,是最好的展现shader能力的例子啊有木有!

      打算后面给编辑看一下合不合适,然后再联系偶像iq征得许可权:)

    这大概是最后一次更新这篇博客了,我上一周在改书的时候虽然对目录小改了下,但大部分内容就是上面这样的。期望后面一切顺利,再次感谢小伙伴们的支持!!!关于出版时间、书名和封面之类的我会在后面不断跟进的!

    展开全文
  • 漫谈一条SQL语句的一生

    万次阅读 多人点赞 2020-03-20 11:32:26
    个默默无闻的垂钓者 --- 来自城管副队长小王 前言 其实,在我们程序员看来,写SQL就像吃饭一样稀松平常。从前,公司大神(侨总)对我说过:"知道么,我写过的SQL比你吃过的米都多"。这句话让我看到了我与他...

    小伙伴想精准查找自己想看的MySQL文章?喏  MySQL专栏目录 | 点击这里

    一个默默无闻的垂钓者 --- 来自城管副队长小王

    前言       

            其实,在我们程序员看来,写SQL就像吃饭一样稀松平常。从前,公司大神(侨总)对我说过:"知道么,我写过的SQL比你吃过的米都多"。这句话让我看到了我与他之间的差距。当然,他不会知道,我们山东人基本不吃米饭。

            言归正传,SQL大家都会写,但有时会不知不觉中留下很多伏笔,造成SQL性能差、浪费服务器资源等等问题。

            我们经常说,看一个事儿千万不要直接陷入细节里,你应该先鸟瞰其全貌,这样能够帮助你从高维度理解问题。这篇文章主要想带你从Mysql内部执行层面了解一条SQL语句完整的执行过程,以及执行过程中各个执行组件的介绍,带你看一看SQL这一生的风景。希望对你以后进行SQL优化或排查问题时有深层次的见解。

     

            平时我们使用数据库,看到的通常都是一个整体。比如,你有个最简单的表,表里只有一个 ID 字段,在执行下面这个查询语句时:

    mysql> select * from T where ID=5;

    我们看到的只是输入一条语句,返回一个结果,却不知道这条语句在 MySQL 内部的执行过程。


    所以今天我想和你一起把 MySQL 拆解一下,看看里面都有哪些“零件”,希望借由这个拆解过程,让你对 MySQL 有更深入的理解。这样当我们碰到 MySQL 的一些异常或者问题时,就能够直戳本质,更为快速地定位并解决问题。

     

    执行流程


    下面我给出的是 MySQL 的基本架构示意图,从中你可以清楚地看到 SQL 语句在 MySQL 的各个功能模块中的执行过程。

    来自《高性能Mysql》


    大体来说,MySQL 可以分为 Server 层和存储引擎层两部分。
    Server 层包括连接器、查询缓存、分析器(预处理器 + 解析树)、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。


    而存储引擎层负责数据的存储和提取。其架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多个存储引擎。现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5.5 版本开始成为了默认存储引擎。
    也就是说,你执行 create table 建表的时候,如果不指定引擎类型,默认使用的就是 InnoDB。不过,你也可以通过指定存储引擎的类型来选择别的引擎,比如在 create table 语句中使用 engine=memory, 来指定使用内存引擎创建表。不同存储引擎的表数据存取方式不同,支持的功能也不同,在后面的文章中,我们会讨论到引擎的选择。


    从图中不难看出,不同的存储引擎共用一个 Server 层,也就是从连接器到执行器的部分。你可以先对每个组件的名字有个印象,接下来我会结合开头提到的那条 SQL 语句,带你走一遍整个执行流程,依次看下每个组件的作用。

     

    组件

     

    1. 连接器


    第一步,你会先连接到这个数据库上,这时候接待你的就是连接器。连接器负责跟客户端建立连接、获取权限、维持和管理连接。连接命令一般是这么写的:

    mysql -h$ip -P$port -u$user -p


    输完命令之后,你就需要在交互对话里面输入密码。虽然密码也可以直接跟在 -p 后面写在命令行中,但这样可能会导致你的密码泄露。如果你连的是生产服务器,强烈建议你不要这么做。


    连接命令中的 mysql 是客户端工具,用来跟服务端建立连接。在完成经典的 TCP 握手后,连接器就要开始认证你的身份,这个时候用的就是你输入的用户名和密码。
    如果用户名或密码不对,你就会收到一个"Access denied for user"的错误,然后客户端程序结束执行。
    如果用户名密码认证通过,连接器会到权限表里面查出你拥有的权限。之后,这个连接里面的权限判断逻辑,都将依赖于此时读到的权限。

     

    这就意味着,一个用户成功建立连接后,即使你用管理员账号对这个用户的权限做了修改,也不会影响已经存在连接的权限。修改完成后,只有再新建的连接才会使用新的权限设置。
    连接完成后,如果你没有后续的动作,这个连接就处于空闲状态,你可以在 show processlist 命令中看到它。文本中这个图是 show processlist 的结果,其中的 Command 列显示为“Sleep”的这一行,就表示现在系统里面有一个空闲连接。

    客户端如果太长时间没动静,连接器就会自动将它断开。这个时间是由参数 wait_timeout 控制的,默认值是 8 小时。
    如果在连接被断开之后,客户端再次发送请求的话,就会收到一个错误提醒: Lost connection to MySQL server during query。这时候如果你要继续,就需要重连,然后再执行请求了。


    数据库里面,长连接是指连接成功后,如果客户端持续有请求,则一直使用同一个连接。短连接则是指每次执行完很少的几次查询就断开连接,下次查询再重新建立一个。
    建立连接的过程通常是比较复杂的,所以我建议你在使用中要尽量减少建立连接的动作,也就是尽量使用长连接。
    但是全部使用长连接后,你可能会发现,有些时候 MySQL 占用内存涨得特别快,这是因为 MySQL 在执行过程中临时使用的内存是管理在连接对象里面的。这些资源会在连接断开的时候才释放。所以如果长连接累积下来,可能导致内存占用太大,被系统强行杀掉(OOM),从现象看就是 MySQL 异常重启了。

    怎么解决这个问题呢?你可以考虑以下两种方案。

    1.
    定期断开长连接。
    使用一段时间,或者程序里面判断执行过一个占用内存的大查询后,断开连接,之后要查询再重连。
    
    2.
    如果你用的是 MySQL 5.7 或更新版本,可以在每次执行一个比较大的操作后,
    通过执行 mysql_reset_connection 来重新初始化连接资源。
    这个过程不需要重连和重新做权限验证,但是会将连接恢复到刚刚创建完时的状态。


    2. 查询缓存


    连接建立完成后,你就可以执行 select 语句了。执行逻辑就会来到第二步:查询缓存。


    MySQL 拿到一个查询请求后,会先到查询缓存看看,之前是不是执行过这条语句。之前执行过的语句及其结果可能会以 key-value 对的形式,被直接缓存在内存中。key 是查询的语句,value 是查询的结果。如果你的查询能够直接在这个缓存中找到 key,那么这个 value 就会被直接返回给客户端。


    如果语句不在查询缓存中,就会继续后面的执行阶段。执行完成后,执行结果会被存入查询缓存中。你可以看到,如果查询命中缓存,MySQL 不需要执行后面的复杂操作,就可以直接返回结果,这个效率会很高。


    但是大多数情况下我会建议你不要使用查询缓存,为什么呢?因为查询缓存往往弊大于利。


    查询缓存的失效非常频繁,只要有对一个表的更新,这个表上所有的查询缓存都会被清空。因此很可能你费劲地把结果存起来,还没使用呢,就被一个更新全清空了。对于更新压力大的数据库来说,查询缓存的命中率会非常低。除非你的业务就是有一张静态表,很长时间才会更新一次。比如,一个功能配置表,那这张表上的查询才适合使用查询缓存。


    好在 MySQL 也提供了这种“按需使用”的方式。你可以将参数 query_cache_type 设置成 DEMAND,这样对于默认的 SQL 语句都不使用查询缓存。而对于你确定要使用查询缓存的语句,可以用 SQL_CACHE 显式指定,像下面这个语句一样:
     

    mysql> select SQL_CACHE * from T where ID=5;

    需要注意的是,MySQL 8.0 版本直接将查询缓存的整块功能删掉了,也就是说 8.0 开始彻底没有这个功能了。

     

    3. 分析器(预处理器 + 解析树)


    如果没有命中查询缓存,就要开始真正执行语句了。首先,MySQL 需要知道你要做什么,因此需要对 SQL 语句做解析。
    分析器先会做“词法分析”。你输入的是由多个字符串和空格组成的一条 SQL 语句,MySQL 需要识别出里面的字符串分别是什么,代表什么。


    MySQL 从你输入的"select"这个关键字识别出来,这是一个查询语句。它也要把字符串“T”识别成“表名 T”,把字符串“ID”识别成“列 ID”。
    做完了这些识别以后,就要做“语法分析”。根据词法分析的结果,语法分析器会根据语法规则,判断你输入的这个 SQL 语句是否满足 MySQL 语法。
    如果你的语句不对,就会收到“You have an error in your SQL syntax”的错误提醒,比如下面这个语句 select 少打了开头的字母“s”。
     

    mysql> elect * from t where ID=1;

    ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'elect * from t where ID=1' at line 1


    一般语法错误会提示第一个出现错误的位置,所以你要关注的是紧接“use near”的内容。

     

    4. 优化器


    经过了分析器,MySQL 就知道你要做什么了。在开始执行之前,还要先经过优化器的处理。
    优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序。比如你执行下面这样的语句,这个语句是执行两个表的 join:
     

    mysql> select * from t1 join t2 using(ID)  where t1.c=10 and t2.d=20;
    既可以先从表 t1 里面取出 c=10 的记录的 ID 值,再根据 ID 值关联到表 t2,再判断 t2 里面 d 的值是否等于 20。
    也可以先从表 t2 里面取出 d=20 的记录的 ID 值,再根据 ID 值关联到 t1,再判断 t1 里面 c 的值是否等于 10。

    这两种执行方法的逻辑结果是一样的,但是执行的效率会有不同,而优化器的作用就是决定选择使用哪一个方案。
    优化器阶段完成后,这个语句的执行方案就确定下来了,然后进入执行器阶段。如果你还有一些疑问,比如优化器是怎么选择索引的,有没有可能选择错等等,没关系,我会在后面的文章中单独展开说明优化器的内容。


    5. 执行器


    MySQL 通过分析器知道了你要做什么,通过优化器知道了该怎么做,于是就进入了执行器阶段,开始执行语句。
    开始执行的时候,要先判断一下你对这个表 T 有没有执行查询的权限,如果没有,就会返回没有权限的错误,如下所示 (在工程实现上,如果命中查询缓存,会在查询缓存返回结果的时候,做权限验证。查询也会在优化器之前调用 precheck 验证权限)。
     

    mysql> select * from T where ID=5;

     

    ERROR 1142 (42000): SELECT command denied to user 'b'@'localhost' for table 'T'


    如果有权限,就打开表继续执行。打开表的时候,执行器就会根据表的引擎定义,去使用这个引擎提供的接口。
    比如我们这个例子中的表 T 中,ID 字段没有索引,那么执行器的执行流程是这样的:

    1.
    调用 InnoDB 引擎接口取这个表的第一行,判断 ID 值是不是 10,如果不是则跳过,如果是则将这行存在结果集中;
    
    2.
    调用引擎接口取“下一行”,重复相同的判断逻辑,直到取到这个表的最后一行。
    
    3.
    执行器将上述遍历过程中所有满足条件的行组成的记录集作为结果集返回给客户端。


    至此,这个语句就执行完成了。


    对于有索引的表,执行的逻辑也差不多。第一次调用的是“取满足条件的第一行”这个接口,之后循环取“满足条件的下一行”这个接口,这些接口都是引擎中已经定义好的。
    你会在数据库的慢查询日志中看到一个 rows_examined 的字段,表示这个语句执行过程中扫描了多少行。这个值就是在执行器每次调用引擎获取数据行的时候累加的。
    在有些场景下,执行器调用一次,在引擎内部则扫描了多行,因此引擎扫描行数跟 rows_examined 并不是完全相同的。

     

    小结


    这篇文章给你介绍了 MySQL 的逻辑架构,希望你对一个 SQL 语句完整执行流程的各个阶段有了一个初步的印象。
     

    参考资料:

    《高性能Mysql》

    极客时间MySQL实战45讲

    展开全文
  • 他说一条河流的水量,是由河流的长度、深度和宽度这三个因素决定的,而一个人的影响力也是如此。 我们每个人都会在意自身的影响力,因为影响力是我们幸福感和满足感的来源之一。我们自己感觉到的幸福感来源是多种...
  • CentOS各版本更换国内源,一条指令搞定,超简单! 前言 CentOS 有个很方便的软件安装工具yum,但是默认安装完CentOS,系统里使用的是国外的CentOS更新源,这就造成了我们使用默认更新源安装或者更新软件时速度很...
  • 如何执行一条sql语句update多条记录

    千次阅读 2013-05-03 20:47:46
    通常情况下,我们会使用以下SQL语句来更新字段值:UPDATE mytable SET myfield='...举个例子,我的博客有三个分类目录(免费资源、教程指南、橱窗展示),这些分类目录的信息存储在数据库表categories中,并且设置了
  • 请前往Github查看最新介绍 AppUpdateGitHub地址 AppUpdate正在征集框架使用者信息,希望得到大家的支持 ...由于Android Q版本限制应用访问外部存储目录(访问需要同时满足两个条件详情见...
  • 文章目录查询最近对一张表的修改记录最后一条新增的数据参考文章: 查询最近对一张表的修改记录 select 表字段,VERSIONS_STARTTIME,VERSIONS_ENDTIME,VERSIONS_OPERATION from 表名 VERSIONS BETWEEN TIMESTAMP ...
  • 2015年最新Android基础入门教程目录(完结版)

    万次阅读 多人点赞 2015-11-23 20:48:12
    2015年最新Android基础入门教程目录(完结版) 前言: 关于《2015年最新Android基础入门教程目录》终于在今天落下了帷幕,全套教程 共148节已编写完毕,附上目录,关于教程的由来,笔者的情况和自学心得,资源分享 ...
  • 种方法(做调整,重新更新目录,还是会出现之前的情况) 把鼠标放在标题和页码之间(“综述”和“4”),按tab键就可生成分隔符 第二种方法(一劳永逸) WORD引用——目录——自定义目录——打印预览框里写了:...
  • 适用于层次化结构,Makefile主要内容都放在顶层目录下的Makefile.env中,子层Makefile包含这个Makefile.env,只要增加一些变量就可以编译,特别方便添加新的功能模块自动解析头文件依赖 我的程序的目录结构是这样的...
  • 一条数据的HBase之旅,简明HBase入门教程-开篇

    万次阅读 多人点赞 2018-03-21 22:21:04
    这是HBase入门系列的第1篇文章,介绍HBase的数据模型、适用场景、集群关键角色、建表流程以及所涉及的HBase基础概念,本文内容...既然HBase也是个数据库,能否用它将现有系统中昂贵的Oracle替换掉?存放于HBase...
  • 文章目录一、 根据相应的唯一主键来判断是否新增或更新 [对事务支持较好]二、根据selectkey判断查询的count值是否为1,然后再进行新增或更新 前言:我们在做批量更新或者插入时候,不想在代码中写sql查询数据库,...
  • 一下把个表搞的数据乱了,只得恢复数据库重新替换过来,可能是where条件没有写好。 update A SET A.cj = b.cj FROM A ,B WHERE A.Name = B.Name 然后根据自己平时积累写下了如下代码,自己可以验证,风险...
  • Cordova热更新、流程与原理篇)

    千次阅读 2018-05-07 20:42:38
    最近需要上线app,所以需要对cordova热更新的整个流程整理下,防止出现问题,项目的结构大致如下:个是vue开发的工程叫Vue-mobile,个是cordova打包app的工程叫Cordova-appVue-mobile工程:Cordova-app工程:...
  • GIS制图课程目录(持续整理)

    万次阅读 多人点赞 2016-10-23 23:34:19
     由于过去一年都没有进行更新,近期终于抽出时间来进行相关知识的整理,因此,对专项技术进行了不同技术线条的梳理。为了方便阅读,特意整理一下全书的目录结构,希望对读者有帮助。由于Esri推出了ArcGIS Pro 桌面...
  • 文章目录前言、SQL简述1.SQL的概述2.SQL的优点3.SQL的分类二、数据库的三大范式三、数据库的数据类型1.整数类型2.浮点数类型和定点数类型九、MySQL数据表简单查询1.简单查询概述2.查询所有字段(方法不唯一只是...
  • -目录索引SQL Server 2008提供了个增强的SQL命令Merge,用法参看MSDN:http://msdn.microsoft.com/zh-cn/library/bb510625.aspx功能:根据与源表联接的结果,对目标表执行插入、更新或删除操作。例如,根据在另...
  • Java次执行多SQL语句

    万次阅读 2017-10-11 19:27:35
    本实例将演示如何次执行多SQL语句,这些SQL语句可以是插入语句、更新语句和删除语句。本实例以myuser数据库中的staff表为例。 | |目录 1技术要点 2代码实现 3程序解读 1技术要点 次...
  • 手把手带你实现Android增量更新

    千次阅读 2016-11-13 17:07:06
    Android增量更新技术在很多公司都在使用,网上也有一些相关的文章,但大家可能未必完全理解实现的方式,本篇博客,我将步步的带大家实现增量更新。为什么需要增量更新?当我们开发完个项目之后,上线维护 , ...
  • Android Studio安装更新终极解决方式

    千次阅读 2015-07-08 11:09:48
    Android Studio安装更新终极解决方式之前写过篇Android SDK无法更新的博文,其实该方式对Android Studio同样有效,大伙可以下载网盘中分享的小软件,若搜索到通道后提示需要更细,也可以选择更新。参考:...
  • QQ空间爬虫分享(天可抓取 400 万数据)

    万次阅读 多人点赞 2016-03-01 13:30:15
    判重使用“内存位”判重,理论上亿数量级的QQ可瞬间判重,内存占用400M+。 爬虫速度可达到单机每天400万数据以上(具体要考虑网速、网络带宽、稳定性等原因。我在学校是400万+,但在公司那边却只有六成的速度,...
  • MySQL批量插入与更新

    万次阅读 多人点赞 2019-05-20 16:07:36
    结果: 1 20 a 2 26 b 3 30 c 4 22 d 注:insert into values 或 insert into select批量插入时,都满足事务的原子性与一致性,一条出错整体都会回滚。在使用insert into select时,MySQL会对select的数据加S(读)...
  • MySQL事务之丢失更新问题

    千次阅读 多人点赞 2019-05-05 19:41:53
    在事务的并发操作中,也就是多个事务同时对同一组数据进行...比如,事务A 修改了一条记录,事务B 在 事务A 提交的同时也进行了一次修改并且提交。当事务A查询的时候,会发现刚才修改的内容没有被修改,好像丢失了更新
  • Android 增量更新完全解析 是增量不是热修复

    万次阅读 多人点赞 2016-10-11 08:45:09
    一直没有写过总结,本来是准备写个总结的,但是列出来几觉得太装逼,也不是什么干货,所以决定换个角度。 那么就聊聊,目前人生中做的最正确的决定,那就是: 写博客。 很多专业人士觉得写博客很low,更有...
  • android 媒体库数据更新解决办法总结

    千次阅读 2014-04-17 09:02:56
    在项目中,我们经常要创建个自己的目录,里面fang
  • 目录服务

    千次阅读 2010-02-26 10:24:00
    1. 目录服务概念摘抄...目录服务器的主要功能是提供资源与地址的对应关系, 比如你想找台网上的共享打印机或主机时, 你需要知道名字就可以了, 而不必去关心它真正的物理位置. 而目录服务器帮助维护这样的资源---地

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 360,867
精华内容 144,346
关键字:

如何只更新一条目录