Note2 MySql 逻辑查询处理
查询操作是关系数据库最为频繁的操作之一,其显得尤为重要。
SQL 语言不同于其他编程语言,明显的区别在于代码的顺序上面,SQL语言中第一个被处理的语言总是FROM子句。
下面来具体分析每个查询处理的阶段:
1、FROM :
对FROM子句的左表a和右表b进行执行笛卡尔积,产生虚拟表VT1
笛卡尔积也称为交叉连接, 连接后数据条数为a*b
2、ON :
对虚拟表VT1进行筛选, 满足条件的行才会插入到虚拟表VT2中去。
一般的编程语言逻辑表达式的值只有TRUE和FALSE两种,在关系数据库中还有三值逻辑表达式。
还有一种UNKNOWN的情况,比如select null = null 返回的是null ,而不是1, select 1= null返回的还是null,结果是未知的。
那么如果2个值都为NULL,用ON过滤,是不是满足合并的条件呢?
是不满足的,对于ON过滤条件下得NULL值比较,比较结果是UNKNOWN,被看做FALSE来处理,即2个NULL不相同,
总结:在产生VT2的时候,会增加一个额外的列表示ON的过滤条件返回值(TRUE、FALSE、UNKOWNN),取出TRUE的记录,产生VT2
PS:有下面2种情况下,2个NULL的值比较是相同的:
GROUP BY 和ORDER BY 。
3、JOIN
默认情况下,多表的连接是内连接,如果指定了外连接(如左连接Left Join 、右连接 Right Join) ,那么会保留未匹配的行作为外部行到VT2中,产生了虚拟表VT3
4、WHERE
对于虚拟表VT3进行WHERE过滤,只有符合条件的记录才会插入到虚拟表VT4中。
2种过滤是不容许的:
4.1 数据还没有分组
select cust_no ,count(cust_no) from order.order where count(cust_no)<2
4.2 没有列选取
select order_no as orderNo ,cust_no as custNo from order.order where custNo = 1133
因为还没有走到select那一步呢。
那么WHERE过滤和ON过滤有什么差别呢?
如果是内连接,那他们是没有差别的,因为没有添加外部行操作,但是如果是外连接,on在过滤完后会再次添加保留被过滤掉的记录,而where 是永久性的过滤。
5、GROUP BY
根据GROUP BY 子句中列,对VT4中得记录进行分组操作,产生VT5
PS:group by一般会和聚合函数一起使用,如SUM \COUNT\ GROUP_CONCAT.
GROUP_CONCAT一般默认连接的是1024个字节,如果超过,会自动截取,可以改变系统默认值。
6、CUBE| ROLLUP
对VT5进行CUBE ROLLUP操作,产生VT6
7、HAVING
对VT6进行having过滤,having过滤是对分组条件的过滤,符合条件的插入到VT7中
having count(o.order_no) <2
8、SELECT
选择指定的列,插入到VT8中
列的别名不能在select中其他别名表达式中使用,如:
select order_no as o, o+1 as n from order.orders
9、DISTINCT
去掉重复的数据,产生VT9
10、ORDER BY
对于VT9 进行排序操作,产生VT10
关系数据库的表中的数据可以看成是一个集合,其实是无序的。有时候,我们不用Order By也可以得到一个结果是有序的,其实不是这样的。
不要为表中的行假定任何特定的顺序,如果需要有序排列,必须使用order by 来排序。
show status like'%sort%'
进行了55269次扫描,扫描了 35918141 行数据,可以通过增加索引来减小排序的开销。
null 在Order by 中被看成最小值,如果升序排列,会第一个选出
11、limit
取出指定行的记录,返回用户,产生VT11 ,在实际运用中使用其分页比较多,有时候查问题时候,直接limit 1会提高速度。
SQL 语言不同于其他编程语言,明显的区别在于代码的顺序上面,SQL语言中第一个被处理的语言总是FROM子句。
下面来具体分析每个查询处理的阶段:
1、FROM :
对FROM子句的左表a和右表b进行执行笛卡尔积,产生虚拟表VT1
笛卡尔积也称为交叉连接, 连接后数据条数为a*b
2、ON :
对虚拟表VT1进行筛选, 满足条件的行才会插入到虚拟表VT2中去。
一般的编程语言逻辑表达式的值只有TRUE和FALSE两种,在关系数据库中还有三值逻辑表达式。
还有一种UNKNOWN的情况,比如select null = null 返回的是null ,而不是1, select 1= null返回的还是null,结果是未知的。
那么如果2个值都为NULL,用ON过滤,是不是满足合并的条件呢?
是不满足的,对于ON过滤条件下得NULL值比较,比较结果是UNKNOWN,被看做FALSE来处理,即2个NULL不相同,
总结:在产生VT2的时候,会增加一个额外的列表示ON的过滤条件返回值(TRUE、FALSE、UNKOWNN),取出TRUE的记录,产生VT2
PS:有下面2种情况下,2个NULL的值比较是相同的:
GROUP BY 和ORDER BY 。
3、JOIN
默认情况下,多表的连接是内连接,如果指定了外连接(如左连接Left Join 、右连接 Right Join) ,那么会保留未匹配的行作为外部行到VT2中,产生了虚拟表VT3
4、WHERE
对于虚拟表VT3进行WHERE过滤,只有符合条件的记录才会插入到虚拟表VT4中。
2种过滤是不容许的:
4.1 数据还没有分组
select cust_no ,count(cust_no) from order.order where count(cust_no)<2
4.2 没有列选取
select order_no as orderNo ,cust_no as custNo from order.order where custNo = 1133
因为还没有走到select那一步呢。
那么WHERE过滤和ON过滤有什么差别呢?
如果是内连接,那他们是没有差别的,因为没有添加外部行操作,但是如果是外连接,on在过滤完后会再次添加保留被过滤掉的记录,而where 是永久性的过滤。
5、GROUP BY
根据GROUP BY 子句中列,对VT4中得记录进行分组操作,产生VT5
PS:group by一般会和聚合函数一起使用,如SUM \COUNT\ GROUP_CONCAT.
GROUP_CONCAT一般默认连接的是1024个字节,如果超过,会自动截取,可以改变系统默认值。
6、CUBE| ROLLUP
对VT5进行CUBE ROLLUP操作,产生VT6
7、HAVING
对VT6进行having过滤,having过滤是对分组条件的过滤,符合条件的插入到VT7中
having count(o.order_no) <2
8、SELECT
选择指定的列,插入到VT8中
列的别名不能在select中其他别名表达式中使用,如:
select order_no as o, o+1 as n from order.orders
9、DISTINCT
去掉重复的数据,产生VT9
10、ORDER BY
对于VT9 进行排序操作,产生VT10
关系数据库的表中的数据可以看成是一个集合,其实是无序的。有时候,我们不用Order By也可以得到一个结果是有序的,其实不是这样的。
不要为表中的行假定任何特定的顺序,如果需要有序排列,必须使用order by 来排序。
show status like'%sort%'
- mysql> show global status like 'sort%';
- +-------------------+----------+
- | Variable_name | Value |
- +-------------------+----------+
- | Sort_merge_passes | 2136 |
- | Sort_range | 81888 |
- | Sort_rows | 35918141 |
- | Sort_scan | 55269 |
进行了55269次扫描,扫描了 35918141 行数据,可以通过增加索引来减小排序的开销。
null 在Order by 中被看成最小值,如果升序排列,会第一个选出
11、limit
取出指定行的记录,返回用户,产生VT11 ,在实际运用中使用其分页比较多,有时候查问题时候,直接limit 1会提高速度。