日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

五个 SQL 查询性能测试题,只有 40% 及格率,你敢来挑战吗?

發布時間:2025/3/16 数据库 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 五个 SQL 查询性能测试题,只有 40% 及格率,你敢来挑战吗? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者 |?董旭陽TonyDong,CSDN 博客專家

責編 | 唐小引

頭圖 | CSDN 下載自東方 IC

出品 | CSDN 博客

下面是 5 個關于索引和 SQL 查詢性能的測試題;其中 4 個題目都是答案二選一,1 個題目是三選一。只要答對 3 個就算及格,是不是貌似很簡單?但實際上只有 40% 的人能夠及格。我們在測試題的后面會給出答案解析,不過建議你先嘗試一下,看看答對幾個!

問題 1

以下查詢語句有沒有性能問題?

CREATE?TABLE?t1?(id?INT?NOT?NULL,dt?DATE,PRIMARY?KEY?(id) ); CREATE?INDEX?idx1?ON?t1(dt);SELECT?*FROM?t1WHERE?TO_CHAR(dt,?'YYYY')?=?'2019';?--?Oracle、PostgreSQL--?WHERE?YEAR(dt)?=?'2019';?--?MySQL--?WHERE?datepart(yyyy,?dt)?=?'2019';?--?SQL?Server

選項 A:沒問題;

選項 B:有問題。

問題 2

以下查詢語句有沒有性能問題?

CREATE?TABLE?t2?(id?INT?NOT?NULL,i??INTdt?DATE,v??VARCHAR(50),PRIMARY?KEY?(id) ); CREATE?INDEX?idx2?ON?t2(i,?dt);SELECT?*FROM?t2WHERE?i?=?99ORDER?BY?dt?DESCFETCH?FIRST?5?ROW?ONLY;?--?Oracle、SQL?Server、PostgreSQL--?OFFSET?0?ROWS?FETCH?FIRST?5?ROW?ONLY;?--?SQL?Server--?LIMIT?5;?--?MySQL

選項 A:沒問題;

選項 B:有問題。

問題 3

下表中的索引有沒有問題?

CREATE?TABLE?t3?(id???INT?NOT?NULL,col1?INT,col2?INT,col3?VARCHAR(50),PRIMARY?KEY?(id) ); CREATE?INDEX?idx3?ON?t3(col1,?col2);SELECT?*FROM?t3WHERE?col1?=?99AND?col2?=?10;SELECT?*FROM?t3WHERE?col2?=?10;

選項 A:沒問題;

選項 B:有問題。

問題 4

以下查詢語句有沒有性能問題?

CREATE?TABLE?t4?(id???INT?NOT?NULL,col1?INT,col2?VARCHAR(50),PRIMARY?KEY?(id) ); CREATE?INDEX?idx4?ON?t4(col2);SELECT?*FROM?t4WHERE?col2?LIKE?'%sql%';

選項 A:沒問題;

選項 B:有問題。

問題 5

假如存在以下表和兩個查詢語句,哪個查詢更快?

CREATE?TABLE?t5?(id???INT?NOT?NULL,col1?INT,col2?INT,col3?VARCHAR(50),PRIMARY?KEY?(id) ); CREATE?INDEX?idx5?ON?t5(col1,?col3);SELECT?col3,?count(*)FROM?t5WHERE?col1?=?99GROUP?BY?col3;SELECT?col3,?count(*)FROM?t5WHERE?col1?=?99AND?col2?=?10GROUP?BY?col3;

選項 A:第一個查詢更快;

選項 B:第二個查詢更快;

選項 C:兩個查詢性能差不多。

解析

  • 問題 1

答案是:B,性能有問題。因為在索引字段上使用函數或者表達式,會導致索引失效。

你可以使用 EXPLAIN 命令查看該語句的執行計劃,最好先執行一次表的統計分析:

--?Oracle EXPLAIN?PLAN?FOR SELECT?*FROM?t1WHERE?TO_CHAR(dt,?'YYYY')?=?'2019';SELECT?*?FROM?TABLE(dbms_xplan.display); PLAN_TABLE_OUTPUT?????????????????????????????????????????????????????????| --------------------------------------------------------------------------| Plan?hash?value:?3617692013???????????????????????????????????????????????|| --------------------------------------------------------------------------| |?Id??|?Operation?????????|?Name?|?Rows??|?Bytes?|?Cost?(%CPU)|?Time?????|| --------------------------------------------------------------------------| |???0?|?SELECT?STATEMENT??|??????|?????1?|????22?|?????2???(0)|?00:00:01?|| |*??1?|??TABLE?ACCESS?FULL|?T1???|?????1?|????22?|?????2???(0)|?00:00:01?|| --------------------------------------------------------------------------|| Predicate?Information?(identified?by?operation?id):???????????????????????| ---------------------------------------------------???????????????????????||1?-?filter(TO_CHAR(INTERNAL_FUNCTION("DT"),'YYYY')='2019')?????????????|| Note??????????????????????????????????????????????????????????????????????| -----?????????????????????????????????????????????????????????????????????|-?dynamic?statistics?used:?dynamic?sampling?(level=2)??????????????????|

Oracle 中是全表掃描,沒有走索引。再看 MySQL:

--?MySQL EXPLAIN?SELECT?*FROM?t1WHERE?YEAR(dt)?=?'2019'; id|select_type|table|partitions|type?|possible_keys|key?|key_len|ref|rows|filtered|Extra???????????????????| --|-----------|-----|----------|-----|-------------|----|-------|---|----|--------|------------------------|1|SIMPLE?????|t1???|??????????|index|?????????????|idx1|4??????|???|???1|?????100|Using?where;?Using?index|

MySQL 雖然使用了索引,但是也需要對索引進行轉換判斷;并不是最優方案。

接下來是 SQL Server:

--?SQL?Server SET?STATISTICS?PROFILE?ONSELECT?*FROM?t1WHERE?datepart(yyyy,?dt)?=?'2019'; Rows|Executes|StmtText?????????????????????????????????????????????????????????????????????????????????????????????????|StmtId|NodeId|Parent|PhysicalOp|LogicalOp?|Argument????????????????????????????????????????????????????????????????????????????????|DefinedValues?????????????????????????????????|EstimateRows|EstimateIO???????????|EstimateCPU??????????|AvgRowSize|TotalSubtreeCost?????|OutputList????????????????????????????????????|Warnings|Type????|Parallel|EstimateExecutions| ----|--------|---------------------------------------------------------------------------------------------------------|------|------|------|----------|----------|----------------------------------------------------------------------------------------|----------------------------------------------|------------|---------------------|---------------------|----------|---------------------|----------------------------------------------|--------|--------|--------|------------------|0|???????1|SELECT?*?FROM?t1?WHERE?datepart(yyyy,?dt)?=?'2019'????????????????????????????????????????????????????|?????1|?????1|?????0|??????????|??????????|????????????????????????????????????????????????????????????????????????????????????????|??????????????????????????????????????????????|???????????1|?????????????????????|?????????????????????|??????????|0.0032830999698489904|??????????????????????????????????????????????|????????|SELECT??|???????0|??????????????????|0|???????1|??|--Index?Scan(OBJECT:([hrdb].[dbo].[t1].[idx1]),??WHERE:(datepart(year,[hrdb].[dbo].[t1].[dt])=(2019)))|?????1|?????2|?????1|Index?Scan|Index?Scan|OBJECT:([hrdb].[dbo].[t1].[idx1]),??WHERE:(datepart(year,[hrdb].[dbo].[t1].[dt])=(2019))|[hrdb].[dbo].[t1].[id],?[hrdb].[dbo].[t1].[dt]|???????????1|0.0031250000465661287|1.5809999604243785E-4|????????14|0.0032830999698489904|[hrdb].[dbo].[t1].[id],?[hrdb].[dbo].[t1].[dt]|????????|PLAN_ROW|???????0|?????????????????1|

SQL Server 使用了索引,但是也需要對索引進行轉換判斷;并不是最優方案。

最后看一下 PostgreSQL:

--?PostgreSQL EXPLAIN?SELECT?*FROM?t1WHERE?TO_CHAR(dt,?'YYYY')?=?'2019'; QUERY?PLAN??????????????????????????????????????????????????????????????????????| --------------------------------------------------------------------------------| Seq?Scan?on?t1??(cost=0.00..49.55?rows=11?width=8)??????????????????????????????|Filter:?(to_char((dt)::timestamp?with?time?zone,?'YYYY'::text)?=?'2019'::text)|

PostgreSQL 使用的是全表掃描,沒有使用索引。

正確做法是修改查詢語句:

SELECT?*FROM?tWHERE?dt?BETWEEN?DATE?'2019-01-01'?AND?DATE?'2019-12-31';

備注:使用函數索引并不是最優解決方法,它只能用于特定的查詢條件;如果查詢條件改成 TO_CHAR(dt, 'YYYY-MM-DD') = '2019-06-01'或者其他形式就無法使用該索引了。

  • 問題 2

答案是:A,性能沒有問題。該語句的 WHERE 子句以及 ORDER BY 子句都可以使用索引(反向掃描),不需要對任何行進行額外的排序。可以使用上面的方法查看執行計劃。

  • 問題 3

答案是:B,索引有問題。因為第二個查詢無法使用索引或者效率不高。雖然有些數據庫可能采用索引跳躍掃描,但是可以通過修改索引字段的順序獲得更好的性能:

CREATE?INDEX?idx3?ON?t3(col2,?col1);

將 col2 放在索引的最左端,兩個查詢都可以利用索引;也就是說,復合索引應該遵循最左前綴原則。另外,基于 col2 再創建一個索引會導致索引重復,不是好的方案。

  • 問題 4

答案是:B,性能有問題。因為在 LIKE 條件中以通配符 % 或者 _ 開始的字符串無法使用索引。不過,以下語句可以使用索引:

SELECT?*FROM?t4WHERE?col2?LIKE?'sql%';

對于 PostgreSQL 而言,還需要在創建索引時指定操作符類:

--?PostgreSQL CREATE?INDEX?idx4?ON?t4(col2?varchar_pattern_ops);
  • 問題 5

答案是:A,第一個查詢更快。因為它只需要通過掃描索引(Index-Only Scan)就可以得到結果;第二個查詢雖然可能返回的數據更少,但是需要通過索引訪問表,也就是回表。

親愛的朋友,你答對了幾個?歡迎留言討論!

文章發布已獲作者授權,CSDN 博文地址:

https://blog.csdn.net/horses/article/details/103028340

有道無術,術可成;有術無道,止于術

歡迎大家關注Java之道公眾號

好文章,我在看??

新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!

總結

以上是生活随笔為你收集整理的五个 SQL 查询性能测试题,只有 40% 及格率,你敢来挑战吗?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。