[20170909]為什麼是12秒.txt

来源:http://www.cnblogs.com/lfree/archive/2017/09/11/7503450.html
-Advertisement-
Play Games

[20170909]為什麼是12秒.txt--//在開發程式時我一般會強調開發儘量不要寫一些自定義函數,往往可能導致CPU忙。--//例子很像這樣:CREATE OR REPLACE FUNCTION get_dept (p_deptno dept.deptno%TYPE) RETURN dept. ...


[20170909]為什麼是12秒.txt

--//在開發程式時我一般會強調開發儘量不要寫一些自定義函數,往往可能導致CPU忙。
--//例子很像這樣:

CREATE OR REPLACE FUNCTION get_dept (p_deptno dept.deptno%TYPE)
   RETURN dept.dname%TYPE
IS
   l_dname   dept.dname%TYPE;
BEGIN
   DBMS_LOCK.sleep (1);

   SELECT dname
     INTO l_dname
     FROM dept
    WHERE deptno = p_deptno;

   RETURN l_dname;
END;
/

--//這樣定義實際上非常不好,如果執行如下,相當於每行都會調用函數get_dept,形成不必要的遞歸.
--//本來應該使用表連接解決的,使用函數,有點像標量子查詢.
--//當時我建議他好好看一下我寫的blog,鏈接如下:
--// http://blog.itpub.net/267265/viewspace-2138042/ => [20170426]為什麼是4秒.txt
--// 結果對方發現在12c for windows下,測試結果與我的測試不符,我重新測試看看.

1.環境:
SCOTT@test01p> @ ver1
PORT_STRING                    VERSION        BANNER                                                                               CON_ID
------------------------------ -------------- -------------------------------------------------------------------------------- ----------
IBMPC/WIN_NT64-9.1.0           12.1.0.1.0     Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production              0

2.建立函數:
CREATE OR REPLACE FUNCTION get_dept (p_deptno dept.deptno%TYPE)
   RETURN dept.dname%TYPE
IS
   l_dname   dept.dname%TYPE;
BEGIN
   DBMS_LOCK.sleep (1);

   SELECT dname
     INTO l_dname
     FROM dept
    WHERE deptno = p_deptno;

   RETURN l_dname;
END;
/

set timing on
set autot traceonly;

SCOTT@test01p> select empno, ename, deptno, get_dept(deptno) c20 from emp;
14 rows selected.
Elapsed: 00:00:14.02
--//執行多次穩定遞歸的數量.需要14秒完成.
Execution Plan
----------------------------------------------------------
Plan hash value: 3956160932
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |    14 |   182 |     3   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| EMP  |    14 |   182 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------
Statistics
----------------------------------------------------------
         14  recursive calls
          0  db block gets
         36  consistent gets
          0  physical reads
          0  redo size
       1130  bytes sent via SQL*Net to client
        544  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         14  rows processed
--//可以發現遞歸執行14次(如果不是,執行多次最後會穩定在14次)

--//換成標量子查詢:
SCOTT@test01p> select empno, ename, deptno, (select get_dept(deptno) from dual )c20 from emp;
14 rows selected.
Elapsed: 00:00:12.04
Execution Plan
----------------------------------------------------------
Plan hash value: 1340320406
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |    14 |   182 |     9   (0)| 00:00:01 |
|   1 |  FAST DUAL        |      |     1 |       |     2   (0)| 00:00:01 |
|   2 |  TABLE ACCESS FULL| EMP  |    14 |   182 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------
Statistics
----------------------------------------------------------
         12  recursive calls
          0  db block gets
         32  consistent gets
          0  physical reads
          0  redo size
       1130  bytes sent via SQL*Net to client
        544  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         14  rows processed
--//執行時間是12秒,遞歸12次.與我在11g下測試不同,11g下測試3秒.

set autot off
alter session set statistics_level=all;

SCOTT@test01p> show array
arraysize 200

SCOTT@test01p> select empno, ename, deptno, (select get_dept(deptno) from dual )c20 from emp;
...

SCOTT@test01p> @ dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  apagxtf1p2puy, child number 1
-------------------------------------
select empno, ename, deptno, (select get_dept(deptno) from dual )c20
from emp
Plan hash value: 1340320406
--------------------------------------------------------------------------------------------------------------------
| Id  | Operation         | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |      1 |        |       |     9 (100)|          |     14 |00:00:00.01 |       8 |
|   1 |  FAST DUAL        |      |     12 |      1 |       |     2   (0)| 00:00:01 |     12 |00:00:00.01 |       0 |
|   2 |  TABLE ACCESS FULL| EMP  |      1 |     14 |   182 |     3   (0)| 00:00:01 |     14 |00:00:00.01 |       8 |
--------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$2 / DUAL@SEL$2
   2 - SEL$1 / EMP@SEL$1
21 rows selected.

--//從執行計劃也可以發現fast dual執行了12次.為什麼?不好理解?要麼3次,要麼14次?什麼也不應該12次.

3.分析:
--//使用10046跟蹤看看
@ 10046on 12
select empno, ename, deptno, (select get_dept(deptno) from dual )c20 from emp;
@ 10046off

--//檢查跟蹤文件.
*** 2017-09-09 21:20:16.366
WAIT #181607424: nam='PL/SQL lock timer' ela= 999265 duration=0 p2=0 p3=0 obj#=665 tim=5412716150
=====================
PARSING IN CURSOR #181597968 len=42 dep=1 uid=109 oct=3 lid=109 tim=5412716418 hv=328320763 ad='7ff13e15ba0' sqlid='56r5sd49t3jrv'
SELECT DNAME FROM DEPT WHERE DEPTNO = :B1
END OF STMT
BINDS #181597968:
 Bind#0
  oacdty=02 mxl=22(21) mxlc=00 mal=00 scl=00 pre=00
  oacflg=03 fl2=1206001 frm=00 csi=00 siz=24 off=0
  kxsbbbfp=212a7fb0  bln=22  avl=02  flg=05
  value=20
EXEC #181597968:c=0,e=8900,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=2852011669,tim=5412725274
FETCH #181597968:c=0,e=28,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=1,plh=2852011669,tim=5412725381
STAT #181597968 id=1 cnt=1 pid=0 pos=1 obj=92285 op='TABLE ACCESS BY INDEX ROWID DEPT (cr=2 pr=0 pw=0 time=30 us cost=1 size=13 card=1)'
STAT #181597968 id=2 cnt=1 pid=1 pos=1 obj=92286 op='INDEX UNIQUE SCAN PK_DEPT (cr=1 pr=0 pw=0 time=19 us cost=0 size=0 card=1)'
CLOSE #181597968:c=0,e=3,dep=1,type=3,tim=5412735882
FETCH #181607424:c=0,e=1019217,p=0,cr=7,cu=0,mis=0,r=1,dep=0,og=1,plh=1340320406,tim=5412735943
WAIT #181607424: nam='SQL*Net message from client' ela= 1165 driver id=1413697536 #bytes=1 p3=0 obj#=665 tim=5412737203
...

d:\tools\rlwrap>grep "BINDS #181597968:" D:\app\oracle\diag\rdbms\test\test\trace\test_ora_6436.trc |wc
     12      24     216

--//確實12次.

d:\tools\rlwrap> grep -A5 "BINDS #181597968:" D:\app\oracle\diag\rdbms\test\test\trace\test_ora_6436.trc | grep "^  value="
  value=20
  value=30
  value=20
  value=30
  value=10
  value=20
  value=10
  value=30
  value=20
  value=30
  value=20
  value=10

SCOTT@test01p> select empno, ename, deptno, (select get_dept(deptno) from dual )c20 from emp;
     EMPNO ENAME          DEPTNO C20
---------- ---------- ---------- --------------------
      7369 SMITH              20 RESEARCH
      7499 ALLEN              30 SALES
      7521 WARD               30 SALES
      7566 JONES              20 RESEARCH
      7654 MARTIN             30 SALES
      7698 BLAKE              30 SALES
      7782 CLARK              10 ACCOUNTING
      7788 SCOTT              20 RESEARCH
      7839 KING               10 ACCOUNTING
      7844 TURNER             30 SALES
      7876 ADAMS              20 RESEARCH
      7900 JAMES              30 SALES
      7902 FORD               20 RESEARCH
      7934 MILLER             10 ACCOUNTING
14 rows selected.

--//對比你可以發現,如果鄰近的值一樣,函數調用僅僅1次.

SCOTT@test01p> select * from (select empno, ename, deptno, lag(deptno,1) over(order by rownum) next from emp) where deptno=next;
     EMPNO ENAME          DEPTNO       NEXT
---------- ---------- ---------- ----------
      7521 WARD               30         30
      7698 BLAKE              30         30

--//這樣減少2次調用,說明12c與11g在標量子查詢上處理與原來不同.不知道是什麼回事,上班再仔細對比看看(與11g).
--//或者是OS版本的問題....
--//一個簡單的驗證,建立一個按照deptno排序的表.
create table empx as select * from emp order by deptno;

SCOTT@test01p> select empno, ename, deptno, (select get_dept(deptno) from dual )c20 from empx;
     EMPNO ENAME          DEPTNO C20
---------- ---------- ---------- --------------------
      7782 CLARK              10 ACCOUNTING
      ...
      7654 MARTIN             30 SALES
14 rows selected.
Elapsed: 00:00:03.03

--//現在3秒...如果這樣執行:

select t.* ,(select get_dept(t.deptno) from dual ) c20 from ( select empno, ename, deptno  from emp order by deptno) t;
...
Elapsed: 00:00:12.00

--//竟然也是12秒.不過看執行計劃馬上明白:
SCOTT@test01p> @ dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  248fpg2995yz8, child number 0
-------------------------------------
select t.* ,(select get_dept(t.deptno) from dual ) c20 from ( select
empno, ename, deptno  from emp order by deptno) t
Plan hash value: 3996307794
------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |      1 |        |       |     9 (100)|          |     14 |00:00:12.00 |      31 |       |       |          |
|   1 |  FAST DUAL         |      |     12 |      1 |       |     2   (0)| 00:00:01 |     12 |00:00:00.01 |       0 |       |       |          |
|   2 |  SORT ORDER BY     |      |      1 |     14 |   182 |     9   (0)| 00:00:01 |     14 |00:00:12.00 |      31 |  2048 |  2048 | 2048  (0)|
|   3 |   TABLE ACCESS FULL| EMP  |      1 |     14 |   182 |     3   (0)| 00:00:01 |     14 |00:00:00.01 |       7 |       |       |          |
------------------------------------------------------------------------------------------------------------------------------------------------
--//可以發現 SORT ORDER BY 消耗12秒.也就是在排序前就進行遞歸調用函數了.
--//對比前面的執行計劃,再次發現奇怪問題,看不出前面的執行計劃12秒消耗在那裡?

--//使用提示MATERIALIZE改寫如下:

SCOTT@test01p> with t as ( select /*+MATERIALIZE */ empno, ename, deptno  from emp order by deptno)  select t.*,(select get_dept(t.deptno) from dual ) c20 from t;
     EMPNO ENAME          DEPTNO C20
---------- ---------- ---------- --------------------
      7782 CLARK              10 ACCOUNTING
      7839 KING               10 ACCOUNTING
      ..
      7654 MARTIN             30 SALES
14 rows selected.
Elapsed: 00:00:03.02

SCOTT@test01p> @ dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  fwvgq6403j0nx, child number 0
-------------------------------------
with t as ( select /*+MATERIALIZE */ empno, ename, deptno  from emp
order by deptno)  select t.*,(select get_dept(t.deptno) from dual ) c20
from t
Plan hash value: 2014637640
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                  | Name                       | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  | Writes |  OMem |  1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT           |                            |      1 |        |       |    11 (100)|          |     14 |00:00:00.01 |      21 |      1 |      1 |       |       |          |
|   1 |  FAST DUAL                 |                            |      3 |      1 |       |     2   (0)| 00:00:01 |      3 |00:00:00.01 |       0 |      0 |      0 |       |       |          |
|   2 |  TEMP TABLE TRANSFORMATION |                            |      1 |        |       |            |          |     14 |00:00:00.01 |      21 |      1 |      1 |       |       |          |
|   3 |   LOAD AS SELECT           |                            |      1 |        |       |            |          |      0 |00:00:00.01 |      11 |      0 |      1 |  1036K|  1036K|          |
|   4 |    SORT ORDER BY           |                            |      1 |     14 |   182 |     3   (0)| 00:00:01 |     14 |00:00:00.01 |       7 |      0 |      0 |  2048 |  2048 | 2048  (0)|
|   5 |     TABLE ACCESS FULL      | EMP                        |      1 |     14 |   182 |     3   (0)| 00:00:01 |     14 |00:00:00.01 |       7 |      0 |      0 |       |       |          |
|   6 |   VIEW                     |                            |      1 |     14 |   322 |     2   (0)| 00:00:01 |     14 |00:00:00.01 |       7 |      1 |      0 |       |       |          |
|   7 |    TABLE ACCESS FULL       | SYS_TEMP_0FD9D660E_18A8CC5 |      1 |     14 |   182 |     2   (0)| 00:00:01 |     14 |00:00:00.01 |       7 |      1 |      0 |       |       |          |
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

4.繼續測試使用 DETERMINISTIC Functions:
--//一般如果在在某個函數定義索引,需要DETERMINISTIC,表示返回結果固定。其實即使不固定,也可以這樣定義。
CREATE OR REPLACE FUNCTION get_dept (p_deptno dept.deptno%TYPE)
   RETURN dept.dname%TYPE
   DETERMINISTIC
IS
   l_dname   dept.dname%TYPE;
BEGIN
   DBMS_LOCK.sleep (1);

   SELECT dname
     INTO l_dname
     FROM dept
    WHERE deptno = p_deptno;

   RETURN l_dname;
END;
/

SCOTT@test01p> select empno, ename, deptno, get_dept(deptno) c20  from emp;
...
14 rows selected.
Elapsed: 00:00:14.01
--//奇怪! 又回到14秒,而在11g下這樣的測試是4秒(註意設置array=200的情況,如果太小,時間會變化).

5.最後補充測試RESULT CACHE的情況:

CREATE OR REPLACE FUNCTION get_dept (p_deptno dept.deptno%TYPE)
   RETURN dept.dname%TYPE
   RESULT_CACHE
IS
   l_dname   dept.dname%TYPE;
BEGIN
   DBMS_LOCK.sleep (1);

   SELECT dname
     INTO l_dname
     FROM dept
    WHERE deptno = p_deptno;

   RETURN l_dname;
END;
/

SCOTT@test01p> select empno, ename, deptno, get_dept(deptno) c20  from emp;
14 rows selected.
Elapsed: 00:00:03.13

SCOTT@test01p> select empno, ename, deptno, get_dept(deptno) c20  from emp;
14 rows selected.
Elapsed: 00:00:00.00

--//第1次執行3秒,第2次執行0秒.修改如下結果一樣.
CREATE OR REPLACE FUNCTION get_dept (p_deptno dept.deptno%TYPE)
   RETURN dept.dname%TYPE
   RESULT_CACHE
   DETERMINISTIC
IS
   l_dname   dept.dname%TYPE;
BEGIN
   DBMS_LOCK.sleep (1);

   SELECT dname
     INTO l_dname
     FROM dept
    WHERE deptno = p_deptno;

   RETURN l_dname;
END;
/


總結:
--//不知道是否是OS版本的問題,有機會安裝12c在linux下重覆測試看看.
--//看來測試環境該轉向12c了....那位有12c for linux的版本測試看看...
--//補充測試11g的情況:
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

SYS@book> GRANT EXECUTE ON SYS.dbms_lock TO SCOTT;
Grant succeeded.

CREATE OR REPLACE FUNCTION get_dept (p_deptno dept.deptno%TYPE)
   RETURN dept.dname%TYPE
IS
   l_dname   dept.dname%TYPE;
BEGIN
   DBMS_LOCK.sleep (1);

   SELECT dname
     INTO l_dname
     FROM dept
    WHERE deptno = p_deptno;

   RETURN l_dname;
END;
/

set timing on
set autot traceonly;
select empno, ename, deptno, (select get_dept(deptno) from dual )c20 from emp;

SCOTT@book> select empno, ename, deptno, (select get_dept(deptno) from dual )c20 from emp;
14 rows selected.
Elapsed: 00:00:03.01
Execution Plan
----------------------------------------------------------
Plan hash value: 1340320406
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |    14 |   182 |     3   (0)| 00:00:01 |
|   1 |  FAST DUAL        |      |     1 |       |     2   (0)| 00:00:01 |
|   2 |  TABLE ACCESS FULL| EMP  |    14 |   182 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------
Statistics
----------------------------------------------------------
          3  recursive calls
          0  db block gets
         13  consistent gets
          0  physical reads
          0  redo size
       1114  bytes sent via SQL*Net to client
        520  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         14  rows processed

--//執行多次,基本穩定在3個遞歸調用.

set autot off
alter session set statistics_level=all;
select empno, ename, deptno, (select get_dept(deptno) from dual )c20 from emp;

SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  apagxtf1p2puy, child number 1
-------------------------------------
select empno, ename, deptno, (select get_dept(deptno) from dual )c20 from emp
Plan hash value: 1340320406
--------------------------------------------------------------------------------------------------------------------
| Id  | Operation         | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |      1 |        |       |     3 (100)|          |     14 |00:00:00.01 |       7 |
|   1 |  FAST DUAL        |      |      3 |      1 |       |     2   (0)| 00:00:01 |      3 |00:00:00.01 |       0 |
|   2 |  TABLE ACCESS FULL| EMP  |      1 |     14 |   182 |     3   (0)| 00:00:01 |     14 |00:00:00.01 |       7 |
--------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$2 / DUAL@SEL$2
   2 - SEL$1 / EMP@SEL$1
21 rows selected.

--//Id=2.starts=3次,也驗證函數調用3次.
--//不知道為什麼,也許12.2.0.N版本跟11g一樣,沒有這個oracle版本等以後再測試吧....






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

-Advertisement-
Play Games
更多相關文章
  • 前面的話 本文將通過多種方式實現紋理文本的效果 背景裁切 對於實現紋理文本的效果,腦海中最直接能想到的辦法可能是背景裁切background-clip 使用線性漸變來填充文本背景 下麵使用一張楓葉的背景,來製作紋理文本 當然了,放一張動態gif圖,也是沒問題的 如果想要讓填充動起來,可以通過anim ...
  • 在學習微信小程式開發過程中,一部分的難點是前端邏輯的處理,也就是對前端JS的代碼編輯;一部分的難點是前端界面的設計展示;本篇隨筆基於一個豆瓣電影介面的小程式開源項目進行重新調整,把其中遇到的相關難點和改進的地方進行討論介紹,希望給大家提供一個參考的思路,本篇隨筆是基於前人小程式的項目基礎上進行的改進... ...
  • 所謂的iOS 國際化,就是根據系統不同的語言自動切換。 首先,如圖: 所謂的iOS 國際化,就是根據系統不同的語言自動切換。 首先,如圖: 1.png 1.png 創建一個.strings文件,以“Localizable.strings”為文件名: 2.png 創建完之後,在XCode的右邊勾選自己 ...
  • 轉載請註明出處: 在Android中可以調用自帶的瀏覽器,或者指定一個瀏覽器來打開一個鏈接。只需要傳入一個uri,可以是鏈接地址。 啟動android預設瀏覽器 在Android程式中我們可以通過發送隱式Intent來啟動系統預設的瀏覽器。如果手機本身安裝了多個瀏覽器而又沒有設置預設瀏覽器的話,系統 ...
  • 以下的測試數據根據環境的不同所耗費的時間有所不同,例如我在騰訊雲上的測試,以及在本機的測試速度相差三倍。但當環境因素一樣的時候,優化sql能夠帶來顯著的提升。 測試表數據:3百萬條數據,12個欄位,存儲引擎:myisam 1 確定搜索一條記錄的時候,加上limit 1 ,以此讓游標查到第一條結果時停 ...
  • 譯者:知數堂星耀隊 MySQL 8.0.2複製新特性 MySQL 8 正在變得原來越好,而且這也在我們MySQL複製研發團隊引起了一陣熱潮。我們一直致力於全面提升MySQL複製,通過引入新的和一些有趣的功能。此外,我們還聽取了社區的建議和反饋。因此,我們很榮幸能夠與你一同見證最新版本(MySQL 8 ...
  • 運算符 算術運算符 “+、-、*、/” 加、減、乘、除 連接運算符 “||” 連接運算符是用來連接字元串的,跟java中的"+"號是一致的。 示例: select 'abc'||'bcd' as 連接後的結果 from dual; select d.dname || '部門' from dept d ...
  • 四周昏暗,是一家小城的酒肆,屋外正是大雪紛飛。 林蔥抖了抖外套,進的店裡來,叫了兩斤熟牛肉,一壺燒酒。 “小二,最近什麼工作有前途啊?” 小二打量了一眼林蔥,只見眼前的客官濃眉大眼,身穿一件半舊西裝,一副黑框眼鏡半藏衣袋之中。遠看像個老壞蛋,近看好像朱時茂一般,越看越覺得有一個工作適合他。 “小二你 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...