[20191218]降序索引疑問4.txt

来源:https://www.cnblogs.com/lfree/archive/2019/12/18/12058084.html
-Advertisement-
Play Games

[20191218]降序索引疑問4.txt--//前幾天優化一個項目,我發現許多表裡面有有隱含欄位,一般開發很少建立函數索引.我自己檢查發現裡面存在大量的降序索引.--//我感覺有點奇怪,為什麼開發要建立大量降序索引有什麼好處呢?--//我在鏈接http://www.itpub.net/thread ...


[20191218]降序索引疑問4.txt

--//前幾天優化一個項目,我發現許多表裡面有有隱含欄位,一般開發很少建立函數索引.我自己檢查發現裡面存在大量的降序索引.
--//我感覺有點奇怪,為什麼開發要建立大量降序索引有什麼好處呢?

--//我在鏈接http://www.itpub.net/thread-2122088-1-1.html裡面問這個問題,sqysl的解答給了我很好的提示,我通過例子說明使用降
--//序索引的一點點好處,通過例子說明:

1.環境:
SCOTT@book> @ 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> alter system set pga_aggregate_target=4G;
System altered.

SCOTT@book> create table t (id1 number,id2 number,vc varchar2(50));
Table created.

create index i_t_id1_id2 on t (id1,id2);
create index i_t_id1desc_id2desc on t (id1 desc,id2 desc);
create index i_t_id1desc_id2 on t (id1 desc,id2 );
create index i_t_id1_id2desc on t (id1 ,id2 desc );

SCOTT@book> insert into t select rownum,rownum,lpad('a',50,'a') from dual connect by level<=1e6;
1000000 rows created.

SCOTT@book> commit ;
Commit complete.

--//分析略.
SCOTT@book> select index_name,index_type,blevel,leaf_blocks,distinct_keys from dba_indexes where owner=user and table_name='T';
INDEX_NAME                     INDEX_TYPE                      BLEVEL LEAF_BLOCKS DISTINCT_KEYS
------------------------------ --------------------------- ---------- ----------- -------------
I_T_ID1_ID2                    NORMAL                               2        2623       1000000
I_T_ID1DESC_ID2DESC            FUNCTION-BASED NORMAL                2        5877       1000000
I_T_ID1DESC_ID2                FUNCTION-BASED NORMAL                2        5618       1000000
I_T_ID1_ID2DESC                FUNCTION-BASED NORMAL                2        2753       1000000
--//無論那種倒序索引,索引都比正序索引大,特別是第1個欄位選擇desc的情況.因為我插入的欄位是自增欄位.
--//倒序索引分裂都是50-50分裂.

2.測試例子:
SCOTT@book> alter session set statistics_level = all;
Session altered.

SCOTT@book> select * from (select * from t where id1<=1e6 order by id1 desc,id2 ) where rownum<=10;
       ID1        ID2 VC
---------- ---------- --------------------------------------------------
   1000000    1000000 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    999999     999999 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    999998     999998 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    999997     999997 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    999996     999996 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    999995     999995 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    999994     999994 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    999993     999993 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    999992     999992 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    999991     999991 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
10 rows selected.

SCOTT@book> @ dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  20hb1uyyqx4tf, child number 0
-------------------------------------
select * from (select * from t where id1<=1e6 order by id1 desc,id2 )
where rownum<=10
Plan hash value: 404407004
-------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                     | Name            | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |                 |      1 |        |       |     4 (100)|          |     10 |00:00:00.01 |       6 |
|*  1 |  COUNT STOPKEY                |                 |      1 |        |       |            |          |     10 |00:00:00.01 |       6 |
|   2 |   VIEW                        |                 |      1 |     10 |   530 |     4   (0)| 00:00:01 |     10 |00:00:00.01 |       6 |
|   3 |    TABLE ACCESS BY INDEX ROWID| T               |      1 |   1000K|    58M|     4   (0)| 00:00:01 |     10 |00:00:00.01 |       6 |
|*  4 |     INDEX RANGE SCAN          | I_T_ID1DESC_ID2 |      1 |     10 |       |     3   (0)| 00:00:01 |     10 |00:00:00.01 |       4 |
-------------------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1
   2 - SEL$2 / from$_subquery$_001@SEL$1
   3 - SEL$2 / T@SEL$2
   4 - SEL$2 / T@SEL$2
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(ROWNUM<=10)
   4 - access("T"."SYS_NC00004$">=HEXTORAW('3BFDFF')  AND "T"."SYS_NC00004$" IS NOT NULL)
       filter(SYS_OP_UNDESCEND("T"."SYS_NC00004$")<=1000000)
32 rows selected.
--//邏輯讀僅僅6個.而其它2個索引都無法達到這樣的效果.

select * from (select /*+ index(t I_T_ID1DESC_ID2DESC) */ * from t where id1<=1e6 order by id1 desc,id2 ) where rownum<=10;
select * from (select /*+ index_desc(t I_T_ID1DESC_ID2DESC) */ * from t where id1<=1e6 order by id1 desc,id2 ) where rownum<=10;

select * from (select /*+ index(t I_T_ID1_ID2) */ * from t where id1<=1e6 order by id1 desc,id2 ) where rownum<=10;
select * from (select /*+ index_desc(t I_T_ID1_ID2) */ * from t where id1<=1e6 order by id1 desc,id2 ) where rownum<=10;
--//結果不在貼出.大家可以自行測試.

3.繼續測試:

SCOTT@book> alter index I_T_ID1DESC_ID2 invisible;
Index altered.

SCOTT@book> select * from (select  * from t where id1<=1e6 order by id1 desc,id2 ) where rownum<=1;
       ID1        ID2 VC
---------- ---------- --------------------------------------------------
   1000000    1000000 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

SCOTT@book> @ dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  2r7j4a5gdhpnj, child number 0
-------------------------------------
select * from (select  * from t where id1<=1e6 order by id1 desc,id2 )
where rownum<=1

Plan hash value: 3299198703

----------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation               | Name | Starts | E-Rows |E-Bytes|E-Temp | Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem | Used-Mem |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |      |      1 |        |       |       | 17500 (100)|          |      1 |00:00:00.38 |    9285 |     74 |       |       |          |
|*  1 |  COUNT STOPKEY          |      |      1 |        |       |       |            |          |      1 |00:00:00.38 |    9285 |     74 |       |       |          |
|   2 |   VIEW                  |      |      1 |   1000K|    50M|       | 17500   (1)| 00:03:30 |      1 |00:00:00.38 |    9285 |     74 |       |       |          |
|*  3 |    SORT ORDER BY STOPKEY|      |      1 |   1000K|    58M|    69M| 17500   (1)| 00:03:30 |      1 |00:00:00.38 |    9285 |     74 |    65M|  2806K|          |
|*  4 |     TABLE ACCESS FULL   | T    |      1 |   1000K|    58M|       |  2744   (1)| 00:00:33 |   1000K|00:00:00.12 |    9285 |     74 |       |       |          |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$1
   2 - SEL$2 / from$_subquery$_001@SEL$1
   3 - SEL$2
   4 - SEL$2 / T@SEL$2

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(ROWNUM<=1)
   3 - filter(ROWNUM<=1)
   4 - filter("ID1"<=1000000)
32 rows selected.
--//oracle選擇全表掃描.

SCOTT@book> alter index I_T_ID1DESC_ID2 visible;
Index altered.

4.再繼續測試:
--//測試第1個欄位正序,第2個欄位倒序的情況.
SCOTT@book> select * from (select  * from t where id1<=1e6 order by id1 ,id2 desc ) where rownum<=5;
       ID1        ID2 VC
---------- ---------- --------------------------------------------------
         1          1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         2          2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         3          3 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         4          4 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         5          5 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

SCOTT@book> @ dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  8f5yj8c3frpnc, child number 0
-------------------------------------
select * from (select  * from t where id1<=1e6 order by id1 ,id2 desc )
where rownum<=5
Plan hash value: 2787951352
-------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                     | Name            | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |                 |      1 |        |       |     4 (100)|          |      5 |00:00:00.01 |       6 |
|*  1 |  COUNT STOPKEY                |                 |      1 |        |       |            |          |      5 |00:00:00.01 |       6 |
|   2 |   VIEW                        |                 |      1 |      5 |   265 |     4   (0)| 00:00:01 |      5 |00:00:00.01 |       6 |
|   3 |    TABLE ACCESS BY INDEX ROWID| T               |      1 |   1000K|    58M|     4   (0)| 00:00:01 |      5 |00:00:00.01 |       6 |
|*  4 |     INDEX RANGE SCAN          | I_T_ID1_ID2DESC |      1 |      5 |       |     3   (0)| 00:00:01 |      5 |00:00:00.01 |       4 |
-------------------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1
   2 - SEL$2 / from$_subquery$_001@SEL$1
   3 - SEL$2 / T@SEL$2
   4 - SEL$2 / T@SEL$2
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(ROWNUM<=5)
   4 - access("ID1"<=1000000)
31 rows selected.
--//可以發現很好第使用I_T_ID1_ID2DESC索引.邏輯讀也很小,僅僅6.

SCOTT@book> alter index I_T_ID1_ID2DESC invisible;
Index altered.

select * from (select  * from t where id1<=1e6 order by id1 ,id2 desc ) where rownum<=1;
SCOTT@book> select * from (select  * from t where id1<=1e6 order by id1 ,id2 desc ) where rownum<=5;
       ID1        ID2 VC
---------- ---------- --------------------------------------------------
         1          1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         2          2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         3          3 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         4          4 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         5          5 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

SCOTT@book> @ dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  8f5yj8c3frpnc, child number 0
-------------------------------------
select * from (select  * from t where id1<=1e6 order by id1 ,id2 desc )
where rownum<=5

Plan hash value: 2145689175

-----------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name            | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  |
-----------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                 |      1 |        |       |     4 (100)|          |      5 |00:00:00.01 |       6 |      1 |
|*  1 |  COUNT STOPKEY                 |                 |      1 |        |       |            |          |      5 |00:00:00.01 |       6 |      1 |
|   2 |   VIEW                         |                 |      1 |      5 |   265 |     4   (0)| 00:00:01 |      5 |00:00:00.01 |       6 |      1 |
|   3 |    TABLE ACCESS BY INDEX ROWID | T               |      1 |   1000K|    58M|     4   (0)| 00:00:01 |      5 |00:00:00.01 |       6 |      1 |
|*  4 |     INDEX RANGE SCAN DESCENDING| I_T_ID1DESC_ID2 |      1 |      5 |       |     3   (0)| 00:00:01 |      5 |00:00:00.01 |       4 |      1 |
-----------------------------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1
   2 - SEL$2 / from$_subquery$_001@SEL$1
   3 - SEL$2 / T@SEL$2
   4 - SEL$2 / T@SEL$2
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(ROWNUM<=5)
   4 - access("T"."SYS_NC00004$" IS NOT NULL AND "T"."SYS_NC00004$">=HEXTORAW('3BFDFF') )
       filter(SYS_OP_UNDESCEND("T"."SYS_NC00004$")<=1000000)
32 rows selected.

--//你會發現一個奇特現象,oracle會使用"倒過來"的一個索引,也就是id1 desc,id2 asc的索引.

SCOTT@book> alter index I_T_ID1DESC_ID2 invisible;
Index altered.

SCOTT@book> select * from (select  * from t where id1<=1e6 order by id1 ,id2 desc ) where rownum<=5;
       ID1        ID2 VC
---------- ---------- --------------------------------------------------
         1          1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         2          2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         3          3 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         4          4 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
         5          5 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

SCOTT@book> @ dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  8f5yj8c3frpnc, child number 0
-------------------------------------
select * from (select  * from t where id1<=1e6 order by id1 ,id2 desc )
where rownum<=5

Plan hash value: 3299198703

----------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation               | Name | Starts | E-Rows |E-Bytes|E-Temp | Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem | Used-Mem |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |      |      1 |        |       |       | 17500 (100)|          |      5 |00:00:00.41 |    9279 |   9269 |       |       |          |
|*  1 |  COUNT STOPKEY          |      |      1 |        |       |       |            |          |      5 |00:00:00.41 |    9279 |   9269 |       |       |          |
|   2 |   VIEW                  |      |      1 |   1000K|    50M|       | 17500   (1)| 00:03:30 |      5 |00:00:00.41 |    9279 |   9269 |       |       |          |
|*  3 |    SORT ORDER BY STOPKEY|      |      1 |   1000K|    58M|    69M| 17500   (1)| 00:03:30 |      5 |00:00:00.41 |    9279 |   9269 |  2048 |  2048 | 2048  (0)|
|*  4 |     TABLE ACCESS FULL   | T    |      1 |   1000K|    58M|       |  2744   (1)| 00:00:33 |   1000K|00:00:00.15 |    9279 |   9269 |       |       |          |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1
   2 - SEL$2 / from$_subquery$_001@SEL$1
   3 - SEL$2
   4 - SEL$2 / T@SEL$2
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(ROWNUM<=5)
   3 - filter(ROWNUM<=5)
   4 - filter("ID1"<=1000000)
32 rows selected.
--//選擇的是全表掃描.

SCOTT@book> alter index i_t_id1desc_id2desc invisible;
Index altered.

SCOTT@book> select * from (select  * from t where id1<=1e6 order by id1 desc ,id2 desc ) where rownum<=1;
       ID1        ID2 VC
---------- ---------- --------------------------------------------------
   1000000    1000000 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

SCOTT@book> @ dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  66z6w3qc77jwp, child number 0
-------------------------------------
select * from (select  * from t where id1<=1e6 order by id1 desc ,id2
desc ) where rownum<=1
Plan hash value: 3873686303

----------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name        | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |             |      1 |        |       |     4 (100)|          |      1 |00:00:00.01 |       4 |
|*  1 |  COUNT STOPKEY                 |             |      1 |        |       |            |          |      1 |00:00:00.01 |       4 |
|   2 |   VIEW                         |             |      1 |      1 |    53 |     4   (0)| 00:00:01 |      1 |00:00:00.01 |       4 |
|   3 |    TABLE ACCESS BY INDEX ROWID | T           |      1 |   1000K|    58M|     4   (0)| 00:00:01 |      1 |00:00:00.01 |       4 |
|*  4 |     INDEX RANGE SCAN DESCENDING| I_T_ID1_ID2 |      1 |      1 |       |     3   (0)| 00:00:01 |      1 |00:00:00.01 |       3 |
----------------------------------------------------------------------------------------------------------------------------------------
--//也能很好的選擇正序索引.

5.總結:
--//通過以上測試,僅僅一種特殊的情況才需要建立倒序索引.存在id1 desc,id2 asc的情況下,建議完全可反過來建立(特別對於自增序列欄位),
--//就是反過來建立索引id1 ,id2 desc,這樣的索引占用磁碟空間更小.
--//其它情況我看不到降序索引的優勢.


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

-Advertisement-
Play Games
更多相關文章
  • 1永久增加ip地址和路由 網卡永久添加ip地址 註釋:ens192為管理地址網卡,請根據實際情況進行修改,網關以192.168.160.1為例 複製一份網卡配置文件命名為ifcfg-ens192:1 cd /etc/sysconfig/network-scripts/ cp ifcfg-ens192 ...
  • 一個應用中決定加緩存(Redis,memcached)之前,要考慮的第一個問題就是,引進了緩存之後,會帶來哪些收益(利),付出哪些代價,引起哪些額外的問題(弊)? 任何新的中間件引進,收益和成本都是伴隨的,只有當利大於弊的情況下,能夠容忍其弊端(徹底解決?沒有額外代價又沒有負面影響,是不可能的,那就 ...
  • 有需要學習交流的友人請加入交流群的咱們一起,有問題一起交流,一起進步!前提是你是學技術的。感謝閱讀! 點此加入該群​jq.qq.com 首先採用Mysql存儲千億級的數據,確實是一項非常大的挑戰。Mysql單表確實可以存儲10億級的數據,只是這個時候性能非常差,項目中大量的實驗證明,Mysql單表容 ...
  • https://blog.csdn.net/zhangsheng_1992/article/details/52598396 https://blog.csdn.net/xiyangyang8110/article/details/52163106 https://blog.csdn.net/wei ...
  • https://sqlserver.code.blog/2019/12/18/realcase-failed-to-upgrade-sql-server-2016-sp2-cu11-installation-success-or-error-status-1648/ ...
  • Redis是一個常用的鍵值對資料庫。本篇分享一下如何輕鬆在睿江雲上實現基於windows的redis開發環境。 1. 登錄睿江雲 點擊右上角登錄框 ​ 進入登錄頁面,輸入賬號密碼登錄 ​ 進入控制台,選擇節點創建虛機 ​ 2. 新建雲主機 進入下一步,創建一臺實驗的雲主機,點擊“雲伺服器管理”。簡單 ...
  • 資料庫備份 例如:備份 /www/wwwroot 下麵的 task.db 資料庫 1.進入資料庫 [root@localhost ~]# sqlite3 /www/wwwroot/task.db 2.備份資料庫 sqlite> .output test.sql sqlite> .dump sqlit ...
  • 簡述問題“統計最新時刻處於某一狀態的設備的數量” 1. 首先子查詢結果,可以看到每個設備最新的狀態信息 2.1 在子查詢的基礎上,對設備狀態進行分組,進行統計每個狀態的設備數量 2.1.1 可以看到處於'火警'狀態的數量是2,沒有問題,但是看下一張圖 2.1.2 可以看到處於'故障'狀態的數量是(n ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...