一文搞懂各种数据库SQL执行计划:MySQL、Oracle等

数据库执行计划,这个听起来有点技术范儿的东西,其实就是数据库在执行咱们写的SQL语句时,具体是怎么一步步操作的详细说明书。
比如说,它是通过索引来查找数据,还是直接全表扫描?两个表要怎么连接,连接的顺序又是什么?这些都能在执行计划里找到答案。
要是咱们写的SQL语句运行起来效率不高,那首先就得看看它的执行计划,找出问题所在。

这篇文章呢,就是想带大家了解一下,在MySQL、Oracle这些数据库里,怎么获取执行计划,以及怎么读懂这些计划。
当然,我也会给大家推荐一些可以深入分析的资料。
现在很多管理工具和开发工具都能直接生成图形化的执行计划,比如MySQLWorkbench、OracleSQLDeveloper等等,不过咱们这次不玩这些,就想用数据库自带的命令来查看执行计划,感觉这样更接地气。

先来个小总结,各种数据库查看执行计划的方法:
MySQL执行计划: 在MySQL里,获取执行计划超级简单,就是在SQL语句前头加个EXPLAIN关键字就行。
执行后,你会得到一个表格,里面包含了1 2 列信息。
这个EXPLAIN关键字支持SELECT、DELETE、INSERT、REPLACE、UPDATE这些语句。
接下来,咱们就得琢磨琢磨这些字段的含义了。
比如,Type这一列,如果是ALL,那就说明是全表扫描;如果是eq_ref,那说明是通过索引来访问数据的。

MySQL 8 .0还新添了个ANALYZE选项,能让咱们看到实际执行时间这些额外信息。
比如,Nested loop inner join表示用的是嵌套循环连接的方式,employees表是驱动表。
cost表示估算的代价,rows表示估计返回的行数;actualtime显示了返回第一行和所有数据行花费的实际时间,后面的rows表示迭代器返回的行数,loops表示迭代器循环的次数。

Oracle执行计划: Oracle提供了好几种查看执行计划的方法,这里咱们就介绍一种:先用EXPLAIN PLAN FOR命令生成并保存执行计划,然后再显示保存的执行计划。
这个EXPLAIN PLAN FOR命令不会运行SQL语句,所以生成的执行计划不一定跟实际执行时的计划一样。
它会把生成的执行计划保存到全局的临时表PLAN_TABLE中,然后咱们再用DBMS_XPLAN这个系统包里的存储过程来格式化显示这个表里的执行计划。

Oracle中的EXPLAIN PLAN FOR支持SELECT、UPDATE、INSERT、DELETE语句。
理解执行计划中各种信息的含义也很重要。
比如,Plan hash value是该语句的哈希值,SQL语句和执行计划会存储在库缓存中,哈希值相同的语句可以重用已有的执行计划;Id是一个序号,但并不代表执行的顺序,执行的顺序要按照缩进来判断,缩进越多的越先执行;Operation表示当前的操作,Name显示了访问的表名、索引名或者子查询等;Rows是Oracle估计的当前操作返回的行数;Cost(%CPU)是Oracle计算执行该操作所需的代价;Time是Oracle估计执行该操作所需的时间;Predicate Information显示了与Id相关的谓词信息。

SQL Server执行计划: SQL Server Management Studio提供了查看图形化执行计划的简单方法,这里咱们介绍一种通过命令查看的方法:SET STATISTICS PROFILE ON。
执行这个命令后,执行的语句会额外返回相应的执行计划。
SQL Server中的执行计划支持SELECT、INSERT、UPDATE、DELETE以及EXECUTE语句。
执行计划各个步骤的执行顺序按照缩进来判断,缩进越多的越先执行,同样缩进的从上至下执行。

PostgreSQL执行计划: PostgreSQL中获取执行计划的方法跟MySQL类似,就是在SQL语句的前面加上EXPLAIN关键字。
PostgreSQL中的EXPLAIN支持SELECT、INSERT、UPDATE、DELETE、VALUES、EXECUTE、DECLARE、CREATE TABLE AS以及CREATE MATERIALIZED VIEW AS语句。
执行计划顺序按照缩进来判断,缩进越多的越先执行,同样缩进的从上至下执行。

以上就是各种数据库查看执行计划的方法,希望能帮到大家!

update 根据排序顺序执行

哈喽大家好,今天想跟大家聊聊MySQL里头的一个小坑,就是关于UPDATE语句和排序顺序的问题。

咱们都知道,直接用UPDATE语句的时候,MySQL它自个儿是不支持直接根据某个排序顺序来更新数据的,这有点儿不爽,对吧?不过别急,咱们有办法解决!
一个常用的方法是,先来个SELECT语句,用上ORDER BY子句,把数据给排个序,然后呢,把这个SELECT语句当子查询用,把它嵌套到UPDATE语句里面去。
这样就能根据我们想要的顺序来更新数据了。
当然啦,这种写法有时候可能会把SQL语句搞得比较复杂,所以写的时候得特别小心,确保语句没错,性能也OK。

还有一种方法是,先建个临时表,把需要更新的数据按照顺序插进去,然后再基于这个临时表来执行UPDATE操作。
这样做的优点是,排序的逻辑比较清晰,但要注意的是,临时表的创建和销毁这些细节,还有得保证数据的一致性。

总的来说呢,因为MySQL不允许在UPDATE语句里直接用ORDER BY,所以我们得用子查询或者临时表这种绕道的方式来实现按排序顺序更新数据。
写这些复杂的SQL语句的时候,一定要多测试几遍,确保它们能正确运行,并且不会给数据库性能带来太大的负担。
另外,还得提醒大家,在UPDATE语句里,SET那边的赋值顺序,单表更新的时候MySQL一般是按从左到右的顺序来处理的,但多表更新的时候,它可就不保证这个顺序了,所以用的时候要特别留意。

好啦,今天就先跟大家分享到这里,希望对大家有帮助!

some嵌套查询的用法

Hey小伙伴们,MySQL从4 .1 1 版本开始就全面支持嵌套查询啦!今天就来给大家分享几个简单的嵌套查询例子,这些例子都来自MySQL官方手册哦。

首先,我们来创建一个表t1 ,然后插入一些数据:
sql CREATE TABLE t1 (s1 INT, s2 CHAR(5 ), s3 FLOAT); INSERT INTO t1 VALUES (1 , '1 ', 1 .0); INSERT INTO t1 VALUES (2 , '2 ', 2 .0);
接下来,看看这个嵌套查询的例子:
sql SELECT sb1 , sb2 , sb3 FROM (SELECT s1 AS sb1 , s2 AS sb2 , s3 2 AS sb3 FROM t1 ) AS sb WHERE sb1 > 1 ;
执行结果会是:2 , '2 ', 4 .0。
注意,下面这个查询是错误的,因为对分组后的集合求均值是不对的:
sql SELECT AVG(SUM(column1 )) FROM t1 GROUP BY column1 ;
正确的做法是使用嵌套查询:
sql SELECT AVG(sum_column1 ) FROM (SELECT SUM(column1 ) AS sum_column1 FROM t1 GROUP BY column1 ) AS t1 ;
再来个行的子查询(RowSubquery)的例子:
sql SELECT FROM t1 WHERE ROW(1 , 2 ) = (SELECT column1 , column2 FROM t2 );
这个查询会返回column1 等于column2 的行。
Row函数里的1 和2 就像是构造参数,相信大家应该都懂。

Exist和NotExist的用法和其他数据库类似,这里简单举几个例子:

范例一:找出有对应城市记录的商店类型:
sql SELECT DISTINCT store_type FROM Stores WHERE EXISTS (SELECT FROM Cities_Stores WHERE Cities_Stores.store_type = Stores.store_type);

范例二:找出没有对应城市记录的商店类型:
sql SELECT DISTINCT store_type FROM Stores WHERE NOT EXISTS (SELECT FROM Cities_Stores WHERE Cities_Stores.store_type = Stores.store_type);

范例三:嵌套使用NotExist:
sql SELECT DISTINCT store_type FROM Stores S1 WHERE NOT EXISTS (SELECT FROM Cities WHERE NOT EXISTS (SELECT FROM Cities_Stores WHERE Cities_Stores.city = Cities.city AND Cities_Stores.store_type = Stores.store_type));
条件关联关系查询也和其他数据库类似:
sql SELECT column1 FROM t1 AS x WHERE x.column1 = (SELECT column1 FROM t2 AS x WHERE x.column1 = (SELECT column1 FROM t3 WHERE x.column2 = t3 .column1 ));
最后,还有一些其他的使用方法和注意事项,比如:

支持子查询的语法有:SELECT、INSERT、UPDATE、DELETE、SET和DO。

子查询可以使用DINSTINCT、GROUPBY、LIMIT、ORDERBY、UNION、ALL、UNIONALL等关键词。

可以使用<、>、<=、>=、=、运算符进行比较,也可以使用ANY、IN和SOME进行集合匹配。

希望这些例子能帮到大家,有更多疑问随时来找我哦!

sql server 怎么查询前n条数据

嘿,小伙伴们,知道不,不同数据库查询前N条数据的方法各有门道呢!我来给你科普一下常见的数据库系统及其查询技巧:
1 . Oracle数据库,用ROWNUM关键字来搞定,比如:SELECT FROM TABLENAME WHERE ROWNUM <= N。

2 . Infomix数据库,直接用FIRST关键字,超简单,代码如下:SELECT FIRST N FROM TABLENAME。

3 . DB2 数据库有两种玩法,要么嵌套查询,要么用FETCH子句。
嵌套查询示例如下:SELECT FROM (SELECT FROM TABLENAME ORDER BY COL1 DESC) WHERE ROWNUM <= N;FETCH子句则是:SELECT COLUMN FROM TABLENAME FETCH FIRST N ROWS ONLY。

4 . SQL Server数据库,TOP关键字帮你轻松上马,代码如下:SELECT TOP N FROM TABLENAME。

5 . Sybase数据库,先设置行计数,再查询,命令是:SET ROWCOUNT N; SELECT FROM TABLENAME。

6 . MySQL数据库,用LIMIT关键字,直接写:SELECT FROM TABLENAME LIMIT N。

7 . FoxPro数据库,TOP和ORDER BY一起用,代码是:SELECT TOP N FROM TABLENAME ORDER BY COLUMN。

在Access里,TOP语句虽然灵活,但也有小限制。
比如,用ORDER BY的时候,记得ORDER BY的字段别有重复值,否则TOP可能不灵。
解决方法就是在ORDER BY后面加上主键ID,比如这样:SELECT TOP 1 0 FROM [tableName] ORDER BY 排序字段1 , id。

子查询的例子也给你准备好了,比如:SELECT TOP 3 FROM [tableName] WHERE id IN (子查询结果,比如1 ,2 ,3 ,4 ) ORDER BY id。

DB2 里用FETCH子句限制行数,代码是:SELECT COLUMN FROM TABLENAME WHERE [querycondition] FETCH FIRST 1 0 ROWS ONLY。

MySQL查询前N条,还是用LIMIT:SELECT FROM TABLENAME WHERE [querycondition] LIMIT 1 0
SQL Server查询前N条,方法多样,比如:SELECT TOP (1 0) FROM TABLENAME WHERE [querycondition],SELECT TOP (1 0) FROM TABLENAME ORDER BY id DESC,还有复杂的:SELECT TOP 6 FROM TABLENAME WHERE id NOT IN (SELECT TOP 4 id FROM TABLENAME)。

最后,Oracle数据库查询前N条,还是用ROWNUM:SELECT FROM TABLENAME WHERE ROWNUM <= 1 0
希望这些小技巧能帮到你,祝查询愉快!