Mysql資料庫存取原理及性能優化

来源:https://www.cnblogs.com/zqhIndex/archive/2022/08/02/16520275.html
-Advertisement-
Play Games

一、Mysql的系統架構圖 二、Mysql存儲引擎 Mysql中的數據是通過一定的方式存儲在文件或者記憶體中的,任何方式都有不同的存儲、查找和更新機制,這意味著選擇不同的方式對於數據的存取有效率的差距。 這種不同的存儲方式在 MySQL中被稱作存儲引擎。 存儲引擎是Mysql資料庫系統的底層組件,數據 ...


一、Mysql的系統架構圖

 二、Mysql存儲引擎

  Mysql中的數據是通過一定的方式存儲在文件或者記憶體中的,任何方式都有不同的存儲、查找和更新機制,這意味著選擇不同的方式對於數據的存取有效率的差距。 這種不同的存儲方式在 MySQL中被稱作存儲引擎。

  存儲引擎是Mysql資料庫系統的底層組件,資料庫管理系統通過這些組件來進行創建、查詢、更新和刪除數據,它操作的對象是表。存儲引擎類型在肉眼上體現為表的類型,Mysql的存儲引擎類型可以通過運行命令' SHOW ENGINES;  '獲得,目前Mysql8支持的存儲引擎有如下幾種:

  • FEDERATED:將數據存儲在遠程資料庫中,用來訪問遠程表的存儲引擎。
  • MRG_MYISAM:是一組MyISAM的組合,他將MyISAM引擎的多個表聚合起來,但是他的內部沒有數據,真正的數據依然是MyISAM引擎的表中,但是可以直接進行查詢、刪除更新等操作。
  • MyISAM:是MySQL早期預設的存儲引擎,擁有較高的插入、查詢速度,表鎖設計,支持全文索引,但不支持事務和外鍵。
  • BLACKHOLE:充當一個“黑洞”,接受數據,但將其扔掉,不存儲數據,類似於Linux系統中的/dev/null文件。主要用於查找和存儲引擎無關的其他方面的性能瓶頸。
  • CSV:會在MySQL安裝目錄data文件夾中,和該表所在資料庫名相同的目錄生成一個.CSV文件,它可以將CSV類型的文件當做表進行處理,相比其他存儲引擎的文件內容,可以直接查看和編輯。
  • MEMORY:數據保存在記憶體中,表結構保存在磁碟上。如果資料庫重啟或者發生崩潰,表中的數據都將消失,非常適用於存儲臨時數據的臨時表。
  • ARCHIVE:用於數據存檔的引擎,僅僅支持最基本的插入(insert)和查詢(select)兩種功能。Archive擁有很好的壓縮機制,比MyISAM、InnoDB存儲引擎更加節約存儲空間。
  • InnoDB:是MySQL當前版本預設的存儲引擎,支持事務安全表(ACID),支持行鎖定和外鍵。要求實現併發控制,需要頻繁的更新、刪除操作的資料庫,那選擇InnoDB有很大的優勢。
  • PERFORMANCE_SCHEMA:MySQL資料庫系統專用引擎,用戶不能創建這種存儲引擎的表。

  查看當前預設的存儲引擎:

SHOW VARIABLES LIKE 'default_storage_engine%';

  修改預設存儲引擎(臨時生效,重啟後恢復InnoDB):

SET default_storage_engine=< 存儲引擎名 >

  修改單個數據表的存儲引擎:

ALTER TABLE <表名> ENGINE=<存儲引擎名>;

  查看數據表的存儲引擎:

 SHOW CREATE TABLE tablename \G

  修改表的預設存儲引擎,要想永久生效,需要在配置文件my.cnf中  [mysqld] 後面加入:

default-storage-engine=存儲引擎名稱

  如何根據業務場景來選擇合適自己的存儲引擎呢?這需要先瞭解幾種存儲引擎的特性,以下是幾種存儲引擎的特性表,可做參考:

特性MyISAMInnoDBMEMORY
存儲限制 支持
事務安全 不支持 支持 不支持
鎖機制 表鎖 行鎖 表鎖
B樹索引 支持 支持 支持
哈希索引 不支持 不支持 支持
全文索引 支持 不支持 不支持
集群索引 不支持 支持 不支持
數據緩存   支持 支持
索引緩存 支持 支持 支持
數據可壓縮 支持 不支持 不支持
空間使用 N/A
記憶體使用 中等
批量插入速度
支持外鍵 不支持 支持 不支持

 三、InnoDB存儲引擎存取原理

  InnoDB是最常用的存儲引擎,我們的業務系統在使用Mysql作為資料庫的時候,一般都選擇InnoDB作為存儲引擎,原因是該引擎支持行鎖、索引、事務安裝、主外鍵,而這些特性正是業務系統數據所需要的。

  數據在InnoDB中將被劃分為若幹個頁,頁的大小一般為16KB,以頁作為存取數據的單位,前一節提到InnoDB的數據是存到磁碟上的,而程式代碼需要的數據是在記憶體中的,因此存取數據的操作實際上是磁碟和記憶體之間數據交換的過程。

   以下是Mysql數據頁的結構圖,不同的部分代表著不同的功能,其中:

  • File Header:表示文件的頭部,存儲了一些頁的通用信息。
  • Page Header:表示頁面的頭部,存儲一些有關數據頁的信息。
  • Infimun+supremum:表示兩個虛擬的行記錄(最小記錄和最大記錄)。
  • UserRecord:真正用於存儲數據行的內容。
  • FreeSpace:空閑部分。
  • PageDirectory:頁目錄,記錄了某些記錄的位置。
  • FileTrailer:頁尾,用於校驗頁的完整性。

 

   UserRecord這部分空間是可變的,當向資料庫中插入記錄時,數據會被存到這個位置,UserRecord空間被增加,同時FreeSpace容量會變小,直到空閑空間FreeSpace被用完,如果還有新的數據插入,則引擎會申請新的數據頁再進行存儲。

 

 

  多條數據被存到UserRecord這個位置,那他們之間的物理位置有什麼關係呢?這裡牽涉到兩種主要關係,一種是同一數據頁之間的數據記錄位置關係,另一種是不同數據頁之間的記錄的位置關係。要談記錄的位置關係,我們要瞭解每條記錄的存儲結構。

  每條記錄都包含我們存儲的真實欄位數據和記錄額外的信息數據,一行記錄可以以不同的行格式存在,目前有Compact、Redundant、Dynamic、Compressed等幾種格式,以下是Compact行格式的圖解:

 

 其中,每個屬性說明如下:

名稱大小(bit)描述
預留位1 1 空閑
預留位2 1 空閑
delete_mask 1 標記記錄是否被刪除(0未刪除,1已刪除),當標記為刪除時沒有真實從物理磁碟中刪除,只是代表這塊地址可以被覆寫
min_rec_mask 1 標記記錄是否為B+樹的非葉子節點中的最小記錄(索引時用到)
n_owned 4 當前槽管理的記錄數
heap_no 13 記錄在堆中的相對位置
record_type 3 記錄的類型,0表示普通記錄,1表示B+樹非葉節點記錄,2表示最小記錄,3表示最大記錄
next_record 16 下一條記錄的相對位置
NULL值列表   用於標記和統一管理值為NULL的列
變長欄位長度列表   用於存儲可變長度的欄位的值占用的位元組數

   記錄是以單向鏈表的方式存儲的,因此:

  • 當我們插入一條記錄時,新的記錄會記錄下它在堆中的位置並更新相鄰的前一記錄的next_record值為它的heap_no,更新它的next_record值為它的相鄰位置後一記錄的heap_no值。
  • 當我們刪除記錄時,該記錄的delete_mask會被標記為1,同時相鄰的前一記錄的next_record值被更改為它的下一記錄的heap_no值。

   思考一個問題:如果一個數據表的列欄位很多或者存儲的值太多,一個數據頁存不完怎麼辦?在Compact行格式中,對於占用存儲空間很大的列,在記錄真實數據的地方只存儲一部分數據,把剩餘的數據分散存儲在其它頁中,通過在記錄數據的尾部存儲指向其它頁數據的地址來關聯這些分散的數據。

四、InnoDB索引原理

  我們知道,資料庫使用索引的目的是為了加快查詢速度,那麼MySQL是如何實現索引的呢?

  對於數據行的插入,預設情況下是順序存儲(按主鍵排序)的,查詢的時候將按照插入的順序顯示結果。當一個數據頁存儲欄位較少且欄位值內容較少的時候,很有可能這個數據頁就能夠同時存儲上千行記錄,前一節我們說過,數據是以單向鏈表的方式存儲的,這種存儲方式對於插入來說比較快,而對於查詢來說就比較慢,如果我們需要使用where查詢條件從上千行記錄中獲取滿足條件的記錄,如何才能加快查找速度呢?

  InnoDB引擎為我們提供了一個叫做PageDirectory的頁目錄,這個概念在前面介紹數據頁結構的時候提到過,它用於為數據頁的行記錄提供目錄索引,類似書籍的章節目錄,能夠幫助我們快速定位數據記錄所在的分組,從而加快查詢速度,其實現原理是:將頁內所有非刪除的記錄劃分為N個組,每個組裡最後一條記錄(主鍵最大的記錄)的n_owned屬性記錄了組內的記錄數量,將這條記錄的偏移地址取出按序從File Trailer位置開始向前寫入形成PageDirectory,其中偏移地址稱為'槽',圖示如下:

   根據上圖所示.如果我們要獲取id=4的記錄,可以先通過二分法從目錄頁中快速找到這一記錄所在的頁,然後在快速定位數據記錄所在的位置。

.  通過上面的解析,我們理解了從同一個數據頁中快速查找記錄的方式,再來想一想,如果數據行較多,分散存儲到了多個數據頁里,那又如何快速的確定數據在哪一個數據頁的哪一個分組呢?

  InnoDB為我們提供了"數據頁"概念的同時,也給我們提供了一個叫做"目錄頁"的概念,目錄頁用於存儲數據頁的頁號和頁對應的記錄的最小主鍵(相當存了一組{key,value}鍵值對集合,key主鍵,value為頁號)。因此在執行條件查詢時,先通過主鍵確定記錄所在的頁,在根據頁內的頁目錄定位(通過主鍵定位)到分組,從而快速獲取結果。結構圖示如下:

  

   分析結構圖,發現結構是一棵B+樹,B+樹是一種樹數據結構,通常用於資料庫和操作系統的文件系統中。B+樹的特點是能夠保持數據穩定有序,其插入與修改擁有較穩定的對數時間複雜度。B+樹元素自底向上插入,這與二叉樹恰好相反。B+樹的葉子節點用於存儲真實數據,非葉子節點用於存儲主鍵值和指針(頁碼)。

  前面我們提到數據在插入時是按照主鍵的順序來進行排序存儲的,所以這就是為什麼我們在設計表時建議設置主鍵自增的原因(新增記錄時不會對之前的數據進行重新排列,這會加快插入的速度)。其實一個數據行欄位除了我們自己創建的欄位之外,還存在三個隱藏的欄位row_id(行ID)、transaction_id(事務ID)、roll-pointer(回滾指針),如果我們設計表時沒有設置主鍵,也沒有設置唯一索引,那麼它會自動以隱藏的欄位row_id來作為自增主鍵進行排序存儲。

  思考一個問題:如果一個列的值占用空間較多,會發生什麼?當一行記錄存儲的數據較多時,意味著要使用更多的數據頁,更多的數據頁意味著更多的目錄頁,這會增加" B+結構的高度 ",這也會隱形的降低查詢效率。

  到這裡我們已經知道,對於主鍵欄位來說,它會通過頁目錄和目錄頁的方式來增加數據查詢速度,但是在實際開發中,我們可能還需要通過其他欄位的查詢條件來篩選數據,那麼InnoDB引擎又是如何通過什麼方式來增加查詢速度的呢?

  其實,我們也可以為非主鍵欄位來創目錄頁,這些目錄頁同樣組成了B+樹結構,只不過它的葉子節點存儲的是主鍵值,當通過非主鍵欄位查詢記錄時,首先會通過非主鍵目錄頁B+樹結構查找到主鍵,再去調用主鍵的目錄頁B+樹,去查找真實數據。我們知道,除了可以為單獨為非主鍵欄位的某一個欄位創建索引,還可以使用聯合多個欄位來創建一個索引,這兩種方式的實現方式都是相同的。

  根據前面的分析和探究,我們需要知道如下幾點:

  • InnoDB引擎在磁碟和記憶體之間進行數據傳輸時是以“ 數據頁 ”為基本單位傳輸的。
  • 數據行記錄是以單向鏈表的方式存儲的,特點是插入快,更新和查詢慢。
  • 目錄頁能夠幫助引擎快速定位記錄所在的數據頁。
  • 頁內目錄能夠幫助引擎快速定位記錄所在的分組。
  • 為某個欄位創建索引就相當於為這個欄位創建了一個B+樹結構的目錄頁。
  • 以多個欄位為一體創建了一個索引就相當為這些欄位組合創建了一個B+樹結構的目錄頁。
  • 如果定義表時指定了主鍵和唯一索引,則存儲時將以主鍵和唯一索引的邏輯順序進行物理存儲,這種索引中鍵值的邏輯順序決定了表中相應行的物理順序,這種索引稱為聚集索引,反正稱為非聚集索引。
  •  如果定義表時沒有指定主鍵和唯一索引,則InnoDB會以隱藏的欄位row_id為主鍵進行數據存儲。
  • 綜上前兩點證明,建表時會產生一個聚集索引(每張表值只有一個),聚集索引產生的B+樹結構的葉子節點存儲的是真實數據(完整數據),非葉子節點存儲的是主鍵和頁碼指針。
  • 非聚集索引是手動創建的,用於在聚集索引之外創建目錄頁B+樹,葉子節點存儲的是索引列和主鍵值(不是指針),非葉子節點存儲的是索引列和頁碼指針。
  • 為已經存在大量數據的表創建和修改索引時,可能需要長時間的等待操作,甚至導致資料庫崩潰。

五、表的掃描

  我們已經瞭解了索引的原理,知道了可以為表建立多種索引方式,來加快我們的查詢速度,但是不同的索引類型的查詢效率是有區別的,mysql有幾種表的掃描機制:

  • 全表掃描:遍歷整個主鍵索引的B+樹,並且需要讀葉子節點數據。
  • 全索引掃描:遍歷整個二級索引的B+樹。
  • 回表查詢:對於非聚集索引的查詢,會先查非聚集索引的B+樹定位主鍵值,再用這個值去聚集索引的B+樹上查找數據。

在進行數據查詢是應該儘量使用最小的掃描代價去獲得結果,這是SQL性能優化的核心思想,需要註意的是並非避免全表掃描就能獲得最佳效果,反之在具有多個索引的中,過多的索引組合反而可能導致效果不如全表掃描實在,這就是在創建索引時並非越多越好的原因。

  Mysql給我提供了一個關鍵字explain用於分析和測試sql語句的性能,在SQL語句前增加該關鍵字,運行後會返回SQL執行計劃的信息,通過這些信息,可以幫助我們更好的選擇索引和優化SQL語句,例如運行如下語句得到結果如圖:

 其中,結果集的每個欄位和可能的值說明如下:

id

查詢語句的序號:相同ID:多條記錄表示執行順序由上而下;不同ID:如果是子查詢,id的序號會遞增,id值越大優先順序越高,越先被執行。

select_type

SIMPLE:簡單的select查詢,查詢中不包含子查詢或者UNION。

PRIMARY:查詢中若包含任何複雜的子部分,最外層查詢則被標記為PRIMARY。

SUBQUERY:在SELECT或WHERE列表中包含了子查詢。

DERIUED:在FROM列表中包含的子查詢被標記為DERIVED(衍生)MySQL會遞歸執行這些子查詢,把結果放在臨時表裡。

UNION:若第二個SELECT出現在UNION之後,則被標記為UNION;若UNION包含在FROM子句的子查詢中外層SELECT將被標記為:DERIVED。

UNION RESULT: 從UNION表獲取結果的SELECT。

table 表名:數據來自那張表。
partitions 分區表信息,沒有分區表則為NULL。
type 訪問類型指標,查詢速度由快到慢:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index >ALL。
possible_keys 可能選擇的索引,一個或多個。
key 實際使用的索引。如果為NULL,則沒有使用索引。
key_len 選擇的索引的長度,通常來說越小越好。
ref 和索引匹配的列。
rows 估算的掃描行數,越小越好。
filtered 被條件過濾行數的百分比。
extra

Using filesort:使了用臨時表保存中間結果。

Using index:查詢使用了索引。

Using where:使用了where過濾。

Using join buffer:使用了連接緩存。

impossible where:where子句的值總是false,不能用來獲取任何數據。

六、資料庫優化

  我們已經瞭解了索引的原理,明白了數據頁的存儲結構是一棵B+樹,同時目錄頁存儲結構也是一棵B+樹,能夠通過索引定位數據所在的父節點,減少表的掃面,從而快速找到記錄。但是當存在的索引越多時,查找數據的實現方案就越多,那如何才能儘量讓我們編寫的SQL儘量使用最優的方案呢?

  文章頭部的Mysql架構圖中我們可以看到,我們編寫的SQL語句在經過分析器進行語法分析後,傳遞給優化器,優化器幫助我們選擇索引並生成執行計劃,然後再交給執行器獲取操作結果,但是優化器並非萬能的,它只能為我們執行一些可控的優化。我們還需要從減少數據的碎片存儲、不同類型數據的索引效率、表的掃面機制等方面考慮,特此總結出如下幾個優化和設計規則:

  • 控制欄位長度:在設計表的欄位的時候,根據業務需求,儘量控制欄位的長度空間不浪費,比如存儲身份證號的欄位不超過18個字元,手機號的欄位不超過11位。
  • 控制欄位類型:根據mysql提供的欄位類型特性,來選擇合理的欄位類型存儲業務數據,比如存狀態0和1使用boolean類型而不使用字元類型CHAR(1)。
  • 儘量滿足表設計的三大範式,建立合理的資料庫結構,但同時也要考慮需求本身。
  • 控制熱表數據量:結合業務需求,儘量讓熱表的數據量偏小,必要時採用分庫分表的方式,分表包括垂直分表和水平分表,具體根據業務需求來定。
  • 儘量控制事務儘快提交和回滾,以免造成長時間鎖表鎖行。
  • 儘量減少SQL參與過多的計算邏輯,比如createtime欄位不做時間格式轉換處理。
  • 禁止使用外鍵來約束數據的一致性,如需約束請在業務代碼中實現。
  • 儘量使用自增INT/BIGINT類型作為主鍵,使用CHAR和UUID作為主鍵會導致數據的存儲順序離散,產生磁碟碎片。
  • 統一庫、表、存儲過程的字元集,字元集的不同會導致隱式轉換或報錯,或導致無法使用索引,InnoDB通常推薦使用utf8mb4。
  • 索引會影響插入性能,單表索引數量不建議超過5個,必要時可以建立合適的多列索引並註意其順序。
  • 核心涉密數據加密後存儲,這主要是為了數據泄露安全考慮。
  • 使用INT類型來替代浮點型,避免使用浮點型這種效率較低的類型。
  • 遇到BlOB、TEXT等大對象類型的數據,儘量拆分為單獨表,然後使用主鍵做關聯。
  • 字元類型儘量使用靈活高效的varchar來代替char類型,儘量減少字元串類型的加長更新操作。
  • 日期類型儘量選擇datetime類型,因為timestamp類型只能存儲日期時間為1970-2038年,而char類型查詢效率比datetime低。
  • 多表JOIN時,條件列的數據類型要一致,否則可能導致無法使用索引。
  • 多表JOIN時,將過濾後結果集較小的表作為驅動表。
  • SELECT時儘量不讀取不使用的列,這可以減少IO代價。
  • 減少LIKE  '% xxxx %'格式的使用,該語句會導致查詢不使用索引,必要時可以使用LIKE  ' xxxx %'格式,它會使用首碼索引。
  • 儘量主要' != '條件的使用,這有可能導致全表掃描,當然並非一定會全表掃描,具體情況的具體分析。
  • 當能確定返回結果數量時,最好加上LIMIT N,當查詢到指定數量結果後就會立即結束掃描。
  • 優先使用UNION ALL代替UNION,因為UNION會產生臨時表,前者還不會產生去重的代價。 

七、SQL的慢查詢分析

  SQL的執行總是有一個執行時間的,我們可以給資料庫設置一個時間節點參數long_query_time,當SQL執行超過這個值時,便認為本次查詢是慢查詢,將被記錄到慢查詢日誌中,有利於我們進行性能排查。預設的long_query_time預設值為10s。

開啟慢查詢日誌:

  • 在my.cnf中配置:
[mysqld]
log-slow-queries=/data/mysqldata/slow-query.log  #慢查詢日誌的位置
long_query_time=10   #表示查詢超過10s就作為慢查詢
  • 命令臨時開啟:
set global slow_query_log='ON';  #開啟慢查詢

set global slow_query_log_file='/usr/local/slow.log'; #指定日誌文件路徑

set global long_query_time=10;  #自定慢查詢的時長  

八、常用的SQL演算法設計

  • 使用 WITH RECURSIVE tmp AS 語法實現遞歸查詢,比如獲取數結構的所有子節點Id:
with RECURSIVE  tmp as
(
    select * from work_order_question where id=4
    union all
    select c.* from work_order_question as c,tmp t where c.parent_id=t.id
)
select id from tmp

 


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

-Advertisement-
Play Games
更多相關文章
  • head.s 參考 [github這個博主的][ https://github.com/sunym1993/flash-linux0.11-talk ] 改變棧頂位置 _pg_dir: startup_32: movl $0x10,%eax mov %ax,%ds mov %ax,%es mov % ...
  • 曾經的“小霸王”游戲機,讓我們許多80年後、90後度過了一個歡樂愉快的童年,雖然如今這類游戲機和卡帶幾乎已經退出游戲市場,但經典永遠留在了我們這一代人心中。今天給大家分享的小霸王FC經典游戲600合集,帶你回顧童年,重溫經典!希望大家喜歡! 詳情:FC紅白機游戲600合集for mac(小霸王游戲) ...
  • 哪裡有專業級的NTFS格式讀寫工具?Tuxera NTFS 2021 mac中文版是一款非常好用的NTFS讀寫工具,可以讓您完整的讀寫相容NTFS格式驅動器,對磁碟進行訪問、編輯、存儲和傳輸文件等操作。同時還包括開源磁碟管理器等簡單的格式和硬碟維修檢查和修複。 詳情:Tuxera NTFS 2021 ...
  • RAR Extractor是一款非常優秀的壓縮解壓工具,可以幫助用戶提取和預覽多種格式的包(超過 40 種格式),支持解壓RAR、ZIP、7Z、TAR、GZIP、GZ、BZIP2、LZIP、ACE、ISO、PAX、PKG、APK、LBR、MSI、JAR、XZ、LZMA、BZ、LZH、CAB、CPIO ...
  • 拉取nacos docker pull nacos/nacos-server 創建文件夾 日誌文件夾 mkdir -p /root/apply/docker/apply/nacos/logs/ 配置文件夾 mkdir -p /root/apply/docker/apply/nacos/init.d/ ...
  • Xmind 2022 for Mac是一款非常便捷的製作思維導圖的軟體,它有非常豐富的模板可以使用,製作思維導圖可以幫助用戶更高效的進行學習,理清相關學習內容的思路和大體框架,用戶可以根據自己的需求進行自主設計,也可以直接添加模板。 詳情:Xmind 2022 for Mac(思維導圖軟體) 軟體介 ...
  • 基礎知識 ssh:secure shell protocol,安全的遠程登錄 作用:是建立在應用層基礎上的安全協議,實現數據傳輸過程中數據的加密,代替telent協議 使用tcp協議,埠號為22 ssh服務具體的軟體實現: openSSH dropbear OpenSSH:ssh協議的開源實現,l ...
  • 1.mysql資料庫備份與恢復 1.1 資料庫常用備份方案 資料庫備份方案: 冷備份:先把資料庫服務停掉,然後拷貝資料庫目錄下的文件進行備份 物理備份 溫備份: 熱備份:資料庫服務正常運行情況,直接對資料庫進行備份 全量備份:全部備份 增量備份:第一次全備,第二次在第一次全備更改的基礎上備份 差異備 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...