[20180316]為什麼不使用INDEX FULL SCAN (MIN/MAX).txt

来源:https://www.cnblogs.com/lfree/archive/2018/03/16/8579028.html
-Advertisement-
Play Games

[20180316]為什麼不使用INDEX FULL SCAN (MIN/MAX).txt--//鏈接:http://www.itpub.net/thread-2100456-1-1.html.自己重覆測試看看.1.環境:SCOTT@book> @ &r/ver1PORT_STRING VERSIO ...


[20180316]為什麼不使用INDEX FULL SCAN (MIN/MAX).txt

--//鏈接:http://www.itpub.net/thread-2100456-1-1.html.自己重覆測試看看.

1.環境:

SCOTT@book> @ &r/ver1
PORT_STRING                    VERSION        BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx            11.2.0.4.0     Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

SCOTT@book> create table t as select * from dba_objects ;
Table created.

SCOTT@book> create index i_t_object_id on t(object_id);
Index created.

--//分析表略.Method_Opt => 'FOR ALL COLUMNS SIZE 1 '.

2.測試:
SCOTT@book> select /*+ index(t,i_t_object_id) */ nvl2(max(object_id),max(object_id),3000000)+1 n10 from t;
                  N10
---------------------
                90461

SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  f2u3nkrcsdzbb, child number 0
-------------------------------------
select /*+ index(t,i_t_object_id) */
nvl2(max(object_id),max(object_id),3000000)+1 n10 from t
Plan hash value: 2966233522
---------------------------------------------------------------------------
| Id  | Operation          | Name | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |        |       |   347 (100)|          |
|   1 |  SORT AGGREGATE    |      |      1 |     5 |            |          |
|   2 |   TABLE ACCESS FULL| T    |  86989 |   424K|   347   (1)| 00:00:05 |
----------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1
   2 - SEL$1 / T@SEL$1

--//連索引都不用.設置約束object_id is null 看看.

SCOTT@book> delete from t where object_id is null ;
2 rows deleted.

SCOTT@book> commit ;
Commit complete.

SCOTT@book> alter table t modify(object_id  not null);
Table altered.

SCOTT@book> select /*+ index(t,i_t_object_id) */ nvl2(max(object_id),max(object_id),3000000)+1 n10 from t;
                  N10
---------------------
                90461

SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  f2u3nkrcsdzbb, child number 0
-------------------------------------
select /*+ index(t,i_t_object_id) */
nvl2(max(object_id),max(object_id),3000000)+1 n10 from t
Plan hash value: 4145094723
----------------------------------------------------------------------------------------------
| Id  | Operation                   | Name          | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |               |        |       |   195 (100)|          |
|   1 |  SORT AGGREGATE             |               |      1 |     5 |            |          |
|   2 |   FIRST ROW                 |               |  86989 |   424K|   195   (1)| 00:00:03 |
|   3 |    INDEX FULL SCAN (MIN/MAX)| I_T_OBJECT_ID |  86989 |   424K|   195   (1)| 00:00:03 |
----------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1
   3 - SEL$1 / T@SEL$1
Note
-----
   - Warning: basic plan statistics not available. These are only collected when:
       * hint 'gather_plan_statistics' is used for the statement or
       * parameter 'statistics_level' is set to 'ALL', at session or system level

--//可以使用索引,並且走INDEX FULL SCAN (MIN/MAX).不加提示看看:

SCOTT@book> select /*+ inde111x(t,i_t_object_id) */ nvl2(max(object_id),max(object_id),3000000)+1 n10 from t;
                  N10
---------------------
                90461

SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  1d6mkncu6tjms, child number 0
-------------------------------------
select /*+ inde111x(t,i_t_object_id) */
nvl2(max(object_id),max(object_id),3000000)+1 n10 from t
Plan hash value: 3095383276
----------------------------------------------------------------------------------------
| Id  | Operation             | Name          | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |               |        |       |    54 (100)|          |
|   1 |  SORT AGGREGATE       |               |      1 |     5 |            |          |
|   2 |   INDEX FAST FULL SCAN| I_T_OBJECT_ID |  86989 |   424K|    54   (0)| 00:00:01 |
----------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1
   2 - SEL$1 / T@SEL$1
Note
-----
   - Warning: basic plan statistics not available. These are only collected when:
       * hint 'gather_plan_statistics' is used for the statement or
       * parameter 'statistics_level' is set to 'ALL', at session or system level

--//可以發現不加提示,雖然使用索引,但是執行計划走的是INDEX FAST FULL SCAN.
--//註意看一個細節:cost=54.而前面加提示:cost=195,為什麼會這樣,導致執行計劃認為選擇INDEX FAST FULL SCAN更優.

SCOTT@book> alter session set statistics_level=all;

Session altered.

SCOTT@book> select  max(object_id) n10 from t;
                  N10
---------------------
                90460

SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  df1726cj0y4vz, child number 0
-------------------------------------
select  max(object_id) n10 from t
Plan hash value: 2939893782
--------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                  | Name          | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT           |               |      1 |        |       |     2 (100)|          |      1 |00:00:00.01 |       2 |
|   1 |  SORT AGGREGATE            |               |      1 |      1 |     5 |            |          |      1 |00:00:00.01 |       2 |
|   2 |   INDEX FULL SCAN (MIN/MAX)| I_T_OBJECT_ID |      1 |      1 |     5 |     2   (0)| 00:00:01 |      1 |00:00:00.01 |       2 |
--------------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1
   2 - SEL$1 / T@SEL$1

--//如果取最大值cost=2.問題集中在select /*+ index(t,i_t_object_id) */ nvl2(max(object_id),max(object_id),3000000)+1 n10 from t;的cost如何計算.

--//oraclenvl2,nvl函數有一個特點,要先運算第2,3個參數值.如下例子可以證明:

SYS@book> grant execute on sys.dbms_lock to scott;
Grant succeeded.

--//以scott用戶執行:
CREATE OR REPLACE FUNCTION SCOTT.sleep (seconds IN NUMBER)
RETURN NUMBER AS
BEGIN
  sys.dbms_lock.sleep(seconds);
  RETURN seconds;
END;
/

SCOTT@book> set timing on
SCOTT@book> select nvl2(1,sleep(1),sleep(2)) from dual ;
NVL2(1,SLEEP(1),SLEEP(2))
-------------------------
                        1
Elapsed: 00:00:03.00
--//執行需要時間3秒.也就證明先運算sleep(1),sleep(2),在算第1個參數,oracle不會選擇短路執行路徑.

SCOTT@book> select /*+ index(t,i_t_object_id) */ nvl2(max(object_id),max(object_id),3000000)+1 n10 from t;
                  N10
---------------------
                90461

SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  f2u3nkrcsdzbb, child number 0
-------------------------------------
select /*+ index(t,i_t_object_id) */
nvl2(max(object_id),max(object_id),3000000)+1 n10 from t
Plan hash value: 4145094723
---------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name          | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
---------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |               |      1 |        |       |   195 (100)|          |      1 |00:00:00.01 |       2 |
|   1 |  SORT AGGREGATE             |               |      1 |      1 |     5 |            |          |      1 |00:00:00.01 |       2 |
|   2 |   FIRST ROW                 |               |      1 |  86989 |   424K|   195   (1)| 00:00:03 |      1 |00:00:00.01 |       2 |
|   3 |    INDEX FULL SCAN (MIN/MAX)| I_T_OBJECT_ID |      1 |  86989 |   424K|   195   (1)| 00:00:03 |      1 |00:00:00.01 |       2 |
---------------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1
   3 - SEL$1 / T@SEL$1

--//註意看E-Rows=86989.而前面select  max(object_id) n10 from t;的E-Rows=1.可以認為當執行nvl2(max(object_id),max(object_id),3000000)+1時,
--//第2個參數max(object_id),oracle認為這個是變數,運算86989次.導致成本上升為195,通過10053定位看看.
--//而如果使用nvl函數nvl(max(object_id),3000000)+1,第2參數是常量,不需要這種的運算.

3.10053分析:

SCOTT@book> @ &r/10053on 12
Session altered.

SCOTT@book> Select /*+ index(t,i_t_object_id) */ nvl2(max(object_id),max(object_id),3000000)+1 n10 from t;
                  N10
---------------------
                90461

--//註意要改動sql語句,進行1次硬分析10053才跟蹤到.

SCOTT@book> @ &r/10053off
Session altered.


--//檢查轉儲:
-----------------------------
SYSTEM STATISTICS INFORMATION
-----------------------------
  Using NOWORKLOAD Stats
  CPUSPEEDNW: 3074 millions instructions/sec (default is 100)
  IOTFRSPEED: 4096 bytes per millisecond (default is 4096)
  IOSEEKTIM:  10 milliseconds (default is 10)
  MBRC:       NO VALUE blocks (default is 8)

***************************************
BASE STATISTICAL INFORMATION
***********************
Table Stats::
  Table:  T  Alias:  T
    #Rows: 86989  #Blks:  1270  AvgRowLen:  98.00  ChainCnt:  0.00
Index Stats::
  Index: I_T_OBJECT_ID  Col#: 4
    LVLS: 1  #LB: 193  #DK: 86987  LB/K: 1.00  DB/K: 1.00  CLUF: 1368.00
    User hint to use this index
Access path analysis for T
***************************************
SINGLE TABLE ACCESS PATH
  Single Table Cardinality Estimation for T[T]
  Table: T  Alias: T
    Card: Original: 86989.000000  Rounded: 86989  Computed: 86989.00  Non Adjusted: 86989.00
  Access Path: index (FullScan)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    
    Index: I_T_OBJECT_ID
    resc_io: 194.00  resc_cpu: 18778959
    ix_sel: 1.000000  ix_sel_with_filters: 1.000000
    Cost: 194.51  Resp: 194.51  Degree: 1
  Best:: AccessPath: IndexRange
  Index: I_T_OBJECT_ID
         Cost: 194.51  Degree: 1  Resp: 194.51  Card: 86989.00  Bytes: 0
***************************************
--//註意看下劃線部分  Access Path: index (FullScan).
--//  Best:: AccessPath: IndexRange

--//對比如下的10053轉儲
SCOTT@book> @ &r/10053on 12
Session altered.

SCOTT@book> Select  max(object_id) n10 from t;
                  N10
---------------------
                90460

SCOTT@book> @ &r/10053off
Session altered.

BASE STATISTICAL INFORMATION
***********************
Table Stats::
  Table:  T  Alias:  T
    #Rows: 86989  #Blks:  1270  AvgRowLen:  98.00  ChainCnt:  0.00
Index Stats::
  Index: I_T_OBJECT_ID  Col#: 4
    LVLS: 1  #LB: 193  #DK: 86987  LB/K: 1.00  DB/K: 1.00  CLUF: 1368.00
Access path analysis for T
***************************************
SINGLE TABLE ACCESS PATH
  Single Table Cardinality Estimation for T[T]
  Table: T  Alias: T
    Card: Original: 86989.000000  Rounded: 86989  Computed: 86989.00  Non Adjusted: 86989.00
  Access Path: TableScan
    Cost:  346.74  Resp: 346.74  Degree: 0
      Cost_io: 346.00  Cost_cpu: 27311919
      Resp_io: 346.00  Resp_cpu: 27311919
  Access Path: index (index (FFS))
    Index: I_T_OBJECT_ID
    resc_io: 54.00  resc_cpu: 11812878
    ix_sel: 0.000000  ix_sel_with_filters: 1.000000
  Access Path: index (FFS)
    Cost:  54.32  Resp: 54.32  Degree: 1
      Cost_io: 54.00  Cost_cpu: 11812878
      Resp_io: 54.00  Resp_cpu: 11812878
  Access Path: index (Min/Max)
    Index: I_T_OBJECT_ID
    resc_io: 2.00  resc_cpu: 14443
    ix_sel: 0.000000  ix_sel_with_filters: 0.000000
    Cost: 2.00  Resp: 2.00  Degree: 1
  Best:: AccessPath: IndexRange
  Index: I_T_OBJECT_ID
         Cost: 2.00  Degree: 1  Resp: 2.00  Card: 1.00  Bytes: 0
***************************************

--//可以看出oracle分析得到的最佳執行計劃實際上是Best:: AccessPath: IndexRange.
--//cost的成本實際上是IndexRange的成本.

SCOTT@book> select /*+ index(t) */ count(*) from t where object_id between 1 and 1e6;
  COUNT(*)
----------
     86987

SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  1ypsa9k66p3us, child number 0
-------------------------------------
select /*+ index(t) */ count(*) from t where object_id between 1 and 1e6
Plan hash value: 565091764
-----------------------------------------------------------------------------------------------------------------------------
| Id  | Operation         | Name          | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
-----------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |               |      1 |        |       |   195 (100)|          |      1 |00:00:00.03 |     194 |
|   1 |  SORT AGGREGATE   |               |      1 |      1 |     5 |            |          |      1 |00:00:00.03 |     194 |
|*  2 |   INDEX RANGE SCAN| I_T_OBJECT_ID |      1 |  86987 |   424K|   195   (1)| 00:00:03 |  86987 |00:00:00.02 |     194 |
-----------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1
   2 - SEL$1 / T@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("OBJECT_ID">=1 AND "OBJECT_ID"<=1000000)

--//註:一定要加提示/*+ index(t) */,不然執行計劃會選擇INDEX FAST FULL SCAN.而這樣執行計劃是INDEX RANGE SCAN.cost正好是195.
--//這樣的結果導致執行計劃不會選擇INDEX FULL SCAN (MIN/MAX).

--//實際上可以使用Coalesce參數可以避免短路執行.
SCOTT@book> select Coalesce(1,sleep(1)) from dual ;
COALESCE(1,SLEEP(1))
--------------------
                   1

SCOTT@book> set timing on
SCOTT@book> select Coalesce(1,sleep(1)) from dual ;
COALESCE(1,SLEEP(1))
--------------------
                   1

Elapsed: 00:00:00.01
SCOTT@book> set timing off
--//Coalesce參數可以短路執行.

SCOTT@book> Select /*+ ind111ex(t,i_t_object_id) */ Coalesce(max(object_id),3000000)+1 n10 from t;
                  N10
---------------------
                90461

SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
--------------------------------------
SQL_ID  7m1705d3c8b1c, child number 0
-------------------------------------
Select /*+ ind111ex(t,i_t_object_id) */
Coalesce(max(object_id),3000000)+1 n10 from t

Plan hash value: 2939893782

--------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                  | Name          | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT           |               |      1 |        |       |     2 (100)|          |      1 |00:00:00.01 |       2 |
|   1 |  SORT AGGREGATE            |               |      1 |      1 |     5 |            |          |      1 |00:00:00.01 |       2 |
|   2 |   INDEX FULL SCAN (MIN/MAX)| I_T_OBJECT_ID |      1 |      1 |     5 |     2   (0)| 00:00:01 |      1 |00:00:00.01 |       2 |
--------------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1
   2 - SEL$1 / T@SEL$1

--//最主要問題在於開髮根本不應該使用nvl2函數.nvl,Coalesce就沒有問題.


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在MySQL中,它是按什麼順序或規律去讀取my.cnf配置文件的呢?其實只要你花一點功夫,實驗測試一下就能弄清楚,下麵的實驗環境為5.7.21 MySQL Community Server。其它版本如有不同,請以實際情況為準。 其實,MySQL是按照下麵這個順序來讀取my.cnf: 1: /etc/... ...
  • 一、環境 二、官方源 獲取官方源: 安裝: 安裝之後, /etc/yum.repos.d/目錄下會產生兩個文件:mysql-community-source.repo、mysql-community.repo。 三、創建組和用戶 四、安裝MySQL 由於RHEL7.3中預設安裝了Mariadb,安裝 ...
  • 一、索引的含義和特點 索引是一個單獨的、存儲在磁碟上的資料庫結構,他們包含著對數據表裡所有記錄的引用指針。使用索引用於快速找出某個或多個列中有一特點值的行,所用MySQL列類型都可以被索引,對相關列使用索引是提高查詢操作速度的最佳途徑。 索引是在儲存引擎中實現的,因此,每種存儲引擎的索引都不一定完全 ...
  • 嵌套子查詢是SQL語句中比較常用的一種查詢方法,開發過程中遇到查詢需要將自己的某列作為待查詢的數據,在參考別人的SQL語句的寫法終於實現了自己需要的功能。 不太和諧查詢語句如下: SELECT DISTINCT dbo.a.ProxyID, dbo.a.account AS adminAccount ...
  • MySQL日誌管理 查詢有關日誌的變數:show global variables like '%log%' ; 特別提醒: 如果不明白mysql中的變數請點擊 找到其中的 ”mysql伺服器變數“ 部分 錯誤日誌: 記錄內容: 伺服器啟動和關閉過程中的信息 伺服器運行過程中的錯誤信息 事件調度器運 ...
  • 第一步:添加 MariaDB yum 倉庫 首先在CentOS操作系統中/etc/yum.repos.d/目錄下添加 MariaDB 的YUM配置文件MariaDB.repo文件。 vi /etc/yum.repos.d/MariaDB.repo 在該文件中添加以下內容保存: 第二步:安裝 Mari ...
  • 公用表表達式 (CTE) 具有一個重要的優點,那就是能夠引用其自身,從而創建遞歸 CTE。遞歸 CTE 是一個重覆執行初始 CTE 以返回數據子集直到獲取完整結果集的公用表表達式。 當某個查詢引用遞歸 CTE 時,它即被稱為遞歸查詢。遞歸查詢通常用於返回分層數據,例如:顯示某個組織圖中的雇員或物料清 ...
  • [20180316]共用服務模式和直接路徑讀.txt--//在共用伺服器模式下,執行計劃不會選擇直接路徑讀,通過例子證明.1.環境:SYS@book> @ &r/ver1PORT_STRING VERSION BANNER x86_64/Linux 2.4.xx 11.2.0.4.0 Oracle ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...