0%

Heap 資料表

如果資料表沒有Clustered Index那此表就會是Heap資料表

Heap資料表有個特性是Insert資料快比較快,因為插入資料不需要考慮排序。

適合使用在Log資料表、Event資料表、稽核資料表….一直新增資料,但比較少查詢或更新的表

一般來說Heap資料表很少見,因為都會建議每張表都要有Clustered Index.

另外Heap資料表Data Page沒有像其他B+Tree Index有對於左右Page連結Reference.

Heap資料表中不得不知(forwarding pointer)

假如在Heap資料表更新欄位資料,就可能會造成forwarding pointer如果你資料表有許多forwarding pointer可能就要考慮是否要優化調整….

forwarding pointer會造成Logic read增加,因為在Heap讀取資料使用Allocation scan(依照儲存page順序讀取資料,讀到page有forwarding pointer就會多讀取資料頁)

forwarding pointer是因為原本Page(8KB)塞不下更新後資料就會先把資料搬到另一個新建立Page上並在原本Page建立一個類似指標東西指向它.

Read more »

前言:

使用DB新增欄位一般很快就可以執行完畢,但最近我們在prod新增一個bit欄位卻需要跑快45分鐘…

經後面追查找到原因才有本篇文章.

問題重現

下面語法會建立兩個Table.

  • Test:新增10,000,000筆Sample Data
  • TestSplit:新增1,000,000筆Sample Data
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
DROP TABLE IF EXISTS [dbo].[Test]

CREATE TABLE [dbo].[Test](
[ID] [int] NOT NULL IDENTITY(1,1),
[CustomerID] [VARCHAR](40) NOT NULL,
[col1] [VARCHAR](100) SPARSE NULL,
[col2] [VARCHAR](100) SPARSE NULL,
[col3] [VARCHAR](100) SPARSE NULL,
[col4] [VARCHAR](100) SPARSE NULL,
[CreateDate] [datetime2](3) NOT NULL,
) ON [PRIMARY]

CREATE UNIQUE CLUSTERED INDEX CIX_ID ON [dbo].[Test](ID)

INSERT INTO [dbo].[Test] ([CustomerID],Col1,Col2,Col3,Col4,[CreateDate])
SELECT TOP 10000000
REPLICATE('ABCD',10),
REPLICATE('A',100),
REPLICATE('B',100),
REPLICATE('C',100),
REPLICATE('D',100),
SYSDATETIME()
FROM sys.all_columns c1
CROSS JOIN sys.all_columns c2

DROP TABLE IF EXISTS [dbo].[TestSplit]

CREATE TABLE [dbo].[TestSplit](
[ID] [int] NOT NULL IDENTITY(1,1),
[CustomerID] [VARCHAR](40) NOT NULL,
[col1] [VARCHAR](2000) SPARSE NULL,
[col2] [VARCHAR](2000) SPARSE NULL,
[col3] [VARCHAR](2000) SPARSE NULL,
[col4] [VARCHAR](2000) SPARSE NULL,
[CreateDate] [datetime2](3) NOT NULL,
) ON [PRIMARY]

CREATE UNIQUE CLUSTERED INDEX CIX_ID ON [dbo].[TestSplit](ID)

INSERT INTO dbo.[TestSplit] ([CustomerID],Col1,Col2,Col3,Col4,[CreateDate])
SELECT TOP 1000000
REPLICATE('ABCD',10),
REPLICATE('A',2000),
REPLICATE('B',2000),
REPLICATE('C',2000),
REPLICATE('D',2000),
SYSDATETIME()
FROM sys.all_columns c1
CROSS JOIN sys.all_columns c2

我們先在test table新增欄位語法如下

執行下面語法瞬間完成

1
2
3
4
5
6
IF COL_LENGTH('dbo.[Test]','Col6') IS NULL
BEGIN
ALTER TABLE dbo.Test
ADD Col6 BIT NOT NULL
CONSTRAINT DF_Test_Col6 DEFAULT 0
END
Read more »

前言

稍微有經驗的.net工程師一定聽過或使用過Reflection,Reflection雖然好用(能動態處理很多事情)但對於效能會有些影響.

我能否擁有Reflection的動態彈性且兼顧效能呢?

有:就是我們這次要介紹的Expression.

Expression vs Reflection performace

我會準備一個範例來比較ExpressionReflection效能差異

  • Expression
  • Activator.CreateInstance

Activator.CreateInstance Code

Activator.CreateInstance沒甚麼好說就是一個靜態方法傳入Type動態產生一個物件

Expression code

Read more »

前言:

docker透過指令能快速建立相同執行環境並比起VM減少電腦資源消耗.

依照上面優點這就是為什麼docker可以在短時間內快速串紅.

上圖來源《Docker —— 從入門到實踐­》正體中文版

我在網路上找到很棒一個Docker操作流程圖,概括Docker操作時會用到的指令和動作關係.

因為外面有很多blog有對於Docker指令介紹本篇不著重在介紹指令,想要跟大家分享Docker其他細節.

關於Window中的Docker

如果我們需要在Prod運行一個系統可能需要許多不同的程式架構和語言才能完成(甚至有OS限制),在傳統我們選擇使用VM來幫建立不同環境來承載不同程式架構,但VM會模擬OS導致非常肥大,安裝使用資源較大,而Container的Image可以依照我們需求來客製我們需要核心並且Container可以宿主核心達到效能較佳的利用

在Window10 我們可以利用HyperV來跑Docker,原因是HyperV類似一個虛擬機幫我們模擬Linux並且運行Docker Daemon來控管docker container.

Docker需要在Linux中執行,Docker Daemon幫助Client透過命令來操作Docker,如果沒有Docker Daemon我們就無法執行Docker搂.

Read more »

前言

如果我們在Local或測試環境需要建立一個連接MSSQL環境,傳統需要安裝MSSQL和SSMS

但現在有一個更快速輕便方法,就是使用Docker建立MSSQL環境 + VSCode Extension充當SSMS.

安裝時間不僅更快且需要花的空間更小,且可以在Linux使用

Docker建立MSSQL

相信大家都有聽過Docker因為這篇是介紹如何運用Docker建立SSMS,這裡就不介紹太多Docker相關指令意思,有興趣可以自行google.

Window 10才支援docker,因為docker daemon需要在Linux上運作,window需要透過Hyper-V來虛擬化Linux.

如果你是使用Window我推薦下在Docker Desktop,使用UI呈現目前Container有的一些資訊.

如果下載並安裝完Docker可透過docker info命令可以查看,目前Docker使用資訊

Read more »

前文

隨著業務量增長,資料庫的複雜程度也會成正比增長

這裡跟大家分享一個好用壓測資料庫工具SqlQueryStress

在Dev可以模擬高併發時產生的問題,下面會分享我之前Prod遇到問題並解決問題過程

詳細資訊可以看SQLServer-Merge-condition-problem

SQLQueryStress介紹

在執行效能調教和測試高併發產生問題時,我們會關注幾個特別資訊

  1. CPU執行時間
  2. logical read數值
  3. Total執行時間

在此工具都有相對應的資訊提供給我們觀看

Read more »

前文

隨著業務量增長,資料庫的複雜程度也會成正比增長

這裡跟大家分享一個好用壓測資料庫工具SqlQueryStress

在Dev可以模擬高併發時產生的問題,下面會分享我之前Prod遇到問題並解決問題過程

詳細資訊可以看SQLServer-Merge-condition-problem

SQLQueryStress介紹

在執行效能調教和測試高併發產生問題時,我們會關注幾個特別資訊

  1. CPU執行時間
  2. logical read數值
  3. Total執行時間

在此工具都有相對應的資訊提供給我們觀看

Read more »

前言:

在系統中多少會遇到某些交易間需要互斥(不然容易造成DeadLock).

在我們當前系統中有許多動作間需要互斥,不然會有DeadLock問題

藉由已經分析DeadLock Report後,我開始構思如何讓建立Lock可以變得更容易且好理解.

所以就建構出此Lock架構.

如何在此框架使用Lock機制

我們只需要做幾個步驟:

  1. 在使用Lock類別上掛LockerInterceptor攔截器標籤.
  2. 使用Lock方法上使用LockAttribute標籤[Lock(LockKey = "Your lock Key")](Key屬性是必填的)
  3. 設定Lock屬性.

目前寫法是針對單一Server Mutiple Thread來建立互斥Lock. 假如有遇到多台Servers需要建立互斥模式可以,參考Redis的Redlock.Net.

使用方法如下,這樣在多執行緒系統中MethodA1MethodB_A就不會有同時執行問題,這樣就可以造成這兩個動作互斥.

Read more »

前言:

在系統中多少會遇到某些交易間需要互斥(不然容易造成DeadLock).

在我們當前系統中有許多動作間需要互斥,不然會有DeadLock問題

藉由已經分析DeadLock Report後,我開始構思如何讓建立Lock可以變得更容易且好理解.

所以就建構出此Lock架構.

如何在此框架使用Lock機制

我們只需要做幾個步驟:

  1. 在使用Lock類別上掛LockerInterceptor攔截器標籤.
  2. 使用Lock方法上使用LockAttribute標籤[Lock(LockKey = "Your lock Key")](Key屬性是必填的)
  3. 設定Lock屬性.

目前寫法是針對單一Server Mutiple Thread來建立互斥Lock. 假如有遇到多台Servers需要建立互斥模式可以,參考Redis的Redlock.Net.

使用方法如下,這樣在多執行緒系統中MethodA1MethodB_A就不會有同時執行問題,這樣就可以造成這兩個動作互斥.

Read more »

前文:

寫.Net 寫一陣子了 突然覺得一些基本功好重要

之前都沒發現原來.Net 有三種區塊的記憶體空間

這三個區域都有他們各自的含義….

                </div>

.Net 有三種區塊的記憶體空間

Globle:

  1. 全域記憶體
  2. 主要存放全域變數或宣告為static的靜態變數

Heap :

  1. 存放參考類型(可動態產生的空間)
  2. 運行期間分配記憶體位置(這就是為什麼參考類型的類別要new)
  3. 基本是Class關鍵字
Read more »