1. 程式人生 > >SQLTest系列之INSERT語句測試

SQLTest系列之INSERT語句測試

blog rdate load red href 容易 true oca 0.00

原文地址:https://yq.aliyun.com/articles/64375?spm=5176.100239.blogcont69187.22.fhUpoZ

摘要: 一款可以測試MSSQL Server的工具,這篇文章主要是分享下SQLTest之Insert語句測試。

場景引入

菜鳥不斷又猛又持久的給老鳥驚喜以後,老鳥開始不斷的折騰菜鳥:“鳥,你研究下有沒有一款可以測試MSSQL Server的工具吧?”。
“這還不簡單,用Red Gate的SQLTest唄”,於是菜鳥開始了工具的研究之旅:“要不,今天就分享下SQLTest之Insert語句測試吧”。

SQLTest簡介

領了任務的菜鳥,由於之前對這個工具有所了解,所以還是比較輕車熟路的。讓我們先來看看SQLTest是幹什麽的吧。
SQLTest是一款簡單易用,非常容易上手的SQL Server性能、壓力和單元測試工具。它既可以測試本地環境的SQL Server工作負載,也可以測試雲環境的SQL Server服務。

SQLTest一鍵安裝

SQLTest就是一個簡單的SQL Server測試工具,所以,它的安裝過程也簡單。官方推薦一鍵安裝,簡單到令人發指的地步。
技術分享

下載地址:
http://www.sqltest.org/Download

測試環境

在測試之前,菜鳥匯總自己的測試環境信息:

CPU:4 cores
Memory:4 GB
Disk: SSD
SQL Server: SQL Server 2008R2 SP2

SQLTest INSERT語句測試

老實講,上面都不重要,看好了,這裏才是本文的重點:如何使用SQLTest來測試INSERT的效率呢?如何測試INSERT語句在不同線程數量下的效率?不同的數據類型選擇對INSERT效率的影響如何?
這裏虛擬一個場景,假設我們有一張名為Orders的訂單表,我們會根據Orders的主鍵數據類型的不同來測試INSERT的效率。

INT IDENTITY

創建測試數據庫和Orders表

use master;

IF DB_ID
(SQLTestDemo) IS NULL CREATE DATABASE SQLTestDemo go use SQLTestDemo go IF OBJECT_ID(Orders,U) IS NOT NULL BEGIN TRUNCATE TABLE Orders DROP TABLE Orders END GO CREATE TABLE Orders ( OrderID INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED , OrderDate datetime , CustomerID int , SourceID int , StatusID int , Amount decimal (18, 2) , OrderDetails char(7000) ) GO

所有準備工作就緒,菜鳥迫不及待的開始測試了,開啟SQLTest,設置SQLClient Connection String

Data Source=(local);Database=SQLTestDemo;Integrated Security=true;Pooling=false

SQL Command

insert into Orders values (getdate (), 1, 1, 1, 1, replicate (a, 7000)) 
go

Number of Threads
技術分享

點擊Start Current按鈕,測試時間10秒後,得到如下截圖:
1個線程運行10秒鐘,叠代了12471次,每次叠代消耗數據庫時間0.000秒。(由於這裏精確到千分之一秒,也就是一毫秒,說明每次叠代耗時少於1毫秒)。
技術分享

現在我們分別將線程數調整為2,4,8,16,32,64,128,256來測試,為了測試的相對準確性,請在測試之前執行“創建測試數據庫和Orders表”中的代碼,重新創建Orders表。SQLTest返回結果的設置方法如下:Settings => Workload Settings
技術分享

測試完畢後,我們可以得到如下表格數據:
技術分享
將這些數據繪制成直方圖和折線圖:
技術分享

從這個圖中,可以很直觀的得出如下結論:

  • 從吞吐量來看:無輸出結果方式遠遠大於有輸出結果方式,前者是後者的兩倍還多;
  • 從數據庫平均耗時來看:無輸出結果效率也遠遠高於有輸出結果方式,後者是前者的兩倍;
  • 從線程數量來看:並不是線程數開得越多,SQL Server吞吐量越大,效率越高;無論是有輸出結果方式還是無輸出結果方式,並發8到16個線程SQL Server的吞吐量達到最大,效率最高;

註意:
最後一個結論不一定適用於所有的SQL Server,因為這個和SQL Server的版本,機器的CPU,Memory,磁盤等有密切的關系,用戶在得到這個值之前需要自己嚴格測試。

提供INT值

完成了主鍵值INT IDENTITY的測試後,菜鳥陷入了疑惑:每個線程如何插入不同的值呢?於是有了這個測試方法:

use SQLTestDemo
go
IF OBJECT_ID(Orders,U) IS NOT NULL
begin
    truncate table Orders
    drop table Orders
end
go
create table Orders (OrderID int primary key clustered
, OrderDate datetime
, CustomerID int
, SourceID int
, StatusID int
, Amount decimal (18, 2)
, OrderDetails char (7000)
)
go

讓每個線程生成不同的OrderID,我們可以使用SQLTest_Thread來代替線程數,SQLTest_Iteration代替叠代次數,最終將SQL Command修改為:

insert into Orders values (({SQLTest_Thread} * 100000) + {SQLTest_Iteration}, getdate(), 1, 1, 1, 1, replicate (a, 7000))
go

技術分享

UNIQUEIDENTIFIER with NEWID()

測試方法類似於“INT IDENTITY”章節,只是Orders表結構和SQL Command不一致。

use SQLTestDemo 
go 
IF OBJECT_ID(Orders,U) IS NOT NULL
begin
    truncate table Orders
    drop table Orders
end
go 
create table Orders (
OrderID uniqueidentifier not null default newid () primary key clustered
, OrderDate datetime
, CustomerID int
, SourceID int
, StatusID int
, Amount decimal (18, 2)
, OrderDetails char (7000)) 
go
SQL Command
insert into Orders values (NEWID(),getdate (), 1, 1, 1, 1, replicate (a, 7000)) 
go

UNIQUEIDENTIFIER with NEWSEQUENTIALID()

同上,測試方法類似於“INT IDENTITY”章節,只是Orders表結構和SQL Command不一致。

use SQLTestDemo 
go 
IF OBJECT_ID(Orders,U) IS NOT NULL
BEGIN
    TRUNCATE TABLE Orders
    DROP TABLE Orders
END
GO 
CREATE TABLE Orders (
OrderID uniqueidentifier default newsequentialid () primary key clustered
, OrderDate datetime
, CustomerID int
, SourceID int
, StatusID int
, Amount decimal (18, 2)
, OrderDetails char (7000)) 
GO
SQL Command
insert into Orders(OrderDate,CustomerID,SourceID,StatusID,Amount,OrderDetails) values (getdate (), 1, 1, 1, 1, replicate (a, 7000)) 
go

總結

將四種數據類型在No Result輸出情況匯總統計如下表:
技術分享
做一個漂亮炫酷的圖表出來對比下:
技術分享
從這個圖標,我們可以發現如下規律:

  • 從吞吐量角度來看:所有數據類型,並發量聚集在8到16時,INSERT操作吞吐量達到最大值;
  • 吞吐量表現最好的是int identity數據類型和uniqueidentifier + newsequentialid做為主鍵的表;
  • 從數據庫平均耗時角度:所有數據類型,並發量在8到16時,INSERT操作的平均時間消耗最小,接近64個線程時,平均耗時會急劇上升;
  • 平均耗時表現最好的是int identity和Newsequentialid類型。

從結果來看,UNIQUEIDENTIFIER + NEWSEQUENTIALID和INT IDENTITY性能和吞吐量表現都非常好,我們到底該選擇哪一個更好一些呢? 我的結論是選擇IDENTITY屬性的數字類型字段做為主鍵,因為它占的空間更小,INT為4個字節,BIGINT為8個字節而UNIQUEIDENTIFIER 占了36個字節。

SQLTest系列之INSERT語句測試