1. 程式人生 > >SQL Server二進位制聚合運算效能的研究

SQL Server二進位制聚合運算效能的研究

程式開發中涉及許可權管理,系統採用了整形數記錄使用者許可權,許可權級別設定為:

Level1 1
Level2 2
Level3 4
Level4 8
Level5 16
Level6 31
Level7 32
Level8 64
Level9 127
Level10 128
Level11 255
Level12 65535

在資料庫中如果一個使用者a許可權級別為1, 他的三個角色分別被授予許可權2,2,4

則使用者的許可權應該返回7,即1|2|2|4.

由於T-SQL中沒有二進位制的聚合函式,我們的儲存過程中起先使用遊標迴圈記錄逐條進行OR運算,然後輸出結果。在進行壓力測試時發現,當系統壓力達到一定程度時SQL Server伺服器CPU會達到100%,而且一直居高不下。

大家知道,臭名昭著的遊標一直是SQL程式設計人員聲討的物件,於是我改用迴圈讀取表記錄逐條進行OR運算,然後輸出結果。

在同樣的壓力下進行測試,結果仍然不理想。

If you have a numbers table:

SELECT      SUM(mytable.mycolumn),
SUM(DISTINCT Bits.bitval)
FROM        mytable
INNER JOIN (SELECT POWER(2, n-1) AS bitval
FROM   dbo.Numbers
WHERE  n <= 31) AS Bits
ON    mytable.value & Bits.bitval = Bits.bitval;


Or if you don't have one (why not?) and don't want to create one (why
not??????), use this instead:

SELECT SUM(mycolumn),
MAX(mycolum & 1)
+ MAX(mycolum & 2)
+ MAX(mycolum & 4)
+ MAX(mycolum & 8)
+ MAX(mycolum & 16)
(....)
+ MAX(mycolum & 1073741824)
FROM   mytable;

於是又分別按照這兩種方法寫了一遍許可權查詢。

測試指令碼和結果如下:

DECLARE @Access table
(Id INT identity primary key,
 Access INT)


DECLARE @insertCount INT
SET @insertCount=10000

WHILE @insertCount>0
BEGIN

 INSERT INTO @Access(Access)
 SELECT 0 Access
 UNION ALL
 SELECT 1 Access
 UNION ALL
 SELECT 2 Access
 UNION ALL
 SELECT 4 Access
 UNION ALL
 SELECT 8 Access
 UNION ALL
 SELECT 16 Access
 UNION ALL
 SELECT 31 Access
 UNION ALL
 SELECT 32 Access
 UNION ALL
 SELECT 64 Access
 UNION ALL
 SELECT 127 Access
 UNION ALL
 SELECT 128 Access
 UNION ALL
 SELECT 65535 Access
 SET @insertCount = @insertCount - 1
END

DECLARE @SumAccess int
SET @SumAccess=0

--方法1,使用遊標
SELECT getdate()
DECLARE @CurrentAccess INT

DECLARE access_cursor CURSOR FOR
SELECT Access
FROM @Access

OPEN access_cursor
FETCH NEXT FROM access_cursor INTO @CurrentAccess


WHILE @@FETCH_STATUS = 0
BEGIN

SET @[email protected]|@CurrentAccess
FETCH NEXT FROM access_cursor INTO @CurrentAccess

END

CLOSE access_cursor
DEALLOCATE access_cursor

SELECT @SumAccess AS UsingCursor
SELECT getdate()

--方法2,使用迴圈

DECLARE @MinId INT
DECLARE @MaxId INT

SET @SumAccess=0
SELECT @MinId=Min(Id)
FROM @Access

SELECT @MaxId=Max(Id)
FROM @Access

WHILE @MinId<[email protected]
BEGIN
 SELECT @[email protected]|Access
 FROM @Access
 WHERE [email protected]
 
 SET @[email protected]+1
END

SELECT @SumAccess AS UsingWhileLoop
SELECT GETDATE()
--方法3,使用二進位制聚合方法1
SELECT
  (SUM(DISTINCT(Access & 0x000001))
 + SUM(DISTINCT(Access & 0x000002))
 + SUM(DISTINCT(Access & 0x000004))
 + SUM(DISTINCT(Access & 0x000008))
 + SUM(DISTINCT(Access & 0x000010))
 + SUM(DISTINCT(Access & 0x000020))
 + SUM(DISTINCT(Access & 0x000040))
 + SUM(DISTINCT(Access & 0x000080))
 + SUM(DISTINCT(Access & 0x000100))
 + SUM(DISTINCT(Access & 0x000200))
 + SUM(DISTINCT(Access & 0x000400))
 + SUM(DISTINCT(Access & 0x000800))
 + SUM(DISTINCT(Access & 0x001000))
 + SUM(DISTINCT(Access & 0x002000))
 + SUM(DISTINCT(Access & 0x004000))
 + SUM(DISTINCT(Access & 0x008000))

 --可根據許可權的最大值繼續增加,我們的系統中0x008000為最大值
  ) as BitWiseAggre1
FROM @Access;

SELECT GETDATE();

--方法3,使用二進位制聚合方法2
WITH AccessValue (Access)
AS
(
 SELECT 1 --必須寫成1否則如果寫成0x000001 SQL Server會將資料型別預設為varbinary,這樣,下面的處理中將無法進行二進位制OR運算
 UNION ALL
 SELECT 0x000002
 UNION
 SELECT 0x000004
 UNION ALL
 SELECT 0x000008
 UNION ALL
 SELECT 0x000010
 UNION ALL
 SELECT 0x000020
 UNION ALL
 SELECT 0x000040
 UNION ALL
 SELECT 0x000080
 UNION ALL
 SELECT 0x000100
 UNION ALL
 SELECT 0x000200
 UNION ALL
 SELECT 0x000400
 UNION ALL
 SELECT 0x000800
 UNION ALL
 SELECT 0x001000
 UNION ALL
 SELECT 0x002000
 UNION ALL
 SELECT 0x004000
 UNION ALL
 SELECT 0x008000
 --可根據許可權的最大值繼續增加,我們的系統中0x008000為最大值
)

SELECT   
SUM(DISTINCT a.Access) AS BitWiseAggre2
FROM        Access_test t
INNER JOIN AccessValue a
ON    t.Access & a.Access = a.Access

SELECT GETDATE()

100,000 records
Using Cursor 3.28s
Using While Loop 1.34s
Bit wise Aggregate Sum1 2s
Bit wise Aggregate Sum2 0.4s
10,000 records
Using Cursor 0.33s
Using While Loop 0.25s
Bit wise Aggregate Sum1 0.2s
Bit wise Aggregate Sum2 0.033s
1,000 records
Using Cursor 0.15s
Using While Loop 0.12s
Bit wise Aggregate Sum1 0.02s
Bit wise Aggregate Sum2 0s

結論:使用二進位制聚合方法中第二種方法,即定義包含許可權資料的常量表,效能最佳。

相關推薦

SQL Server二進位制聚合運算效能研究

程式開發中涉及許可權管理,系統採用了整形數記錄使用者許可權,許可權級別設定為: Level1 1 Level2 2 Level3 4 Level4 8 Level5 16 Level6 31 Level7 32 Level8 64 Level9 127 Level10 128

SQL Server 效能優化實戰系列(一) SQL Server擴充套件函式的基本概念 使用SQL Server 擴充套件函式進行效能優化 SQL Server Url正則表示式 記憶體常駐 完美解決方案

資料庫伺服器主要用於儲存、查詢、檢索企業內部的資訊,因此需要搭配專用的資料庫系統,對伺服器的相容性、可靠性和穩定性等方面都有很高的要求。        下面是進行籠統的技術點說明,為的是讓大家有一個整體的概念,如果想深入可以逐個擊破;&n

SQL Server字串聚合拼接辦法

文章原地址:https://www.cnblogs.com/stealth7/p/6891211.html 資料範例如下: 要得到的結果目標,獲取type相同的所有names拼接在一起的字串: SqlServer並沒有一個直接拼接字串的函式,下面所提到的方法,只是日常的開發中

sql server 2008億萬資料效能優化例項

最近在開發站長幫手網(www.links.cn)的百度權重查詢工具,資料已達億萬級別,主表為關鍵詞主表(包含百度指數,百度收錄等欄位),字表為網站排名表(1-100)的排名。根據設計慣例,查詢的時候主子表通過關鍵詞欄位關聯查詢,查詢語句如下: select top 1000

使用SQL Server 2008進行優化效能

現今的公司需要易訪問且可用性好的商業資料,以便他們可以在全球市場中獲得一席之地。與易訪問資料的這個需求相呼應,關係資料庫和分析資料庫在規模方面繼續發展,內嵌資料庫和許多產品一起出現,並且許多公司將伺服器合併來減輕管理工作。當公司的資料環境在規模和複雜度方面持續發展的同時,他們

SQL Server溫故系列(4):SQL 查詢之集合運算 & 聚合函式

1、集合運算 1.1、並集運算 UNION 1.2、差集運算 EXCEPT 1.3、交集運算 INTERSECT 1.4、集合運算小結 2、聚合函式 2.1、求行數函式 COUNT 2.2、求和函式 SUM 2.3、求最大值函式 MAX 2.4、求最小值函式 MIN 2.5、求平均值函式 AVG 2.

SQL Server字符串聚合拼接辦法

image code 聚合 個人 lec bsp log 希望 在一起 數據範例如下: 要得到的結果目標,獲取type相同的所有names拼接在一起的字符串: SqlServer並沒有一個直接拼接字符串的函數,下面所提到的方法,只是日常的開發中自己個人用到的一些思路,僅

SQL Server聚合函數

值類型 tex 字段名 字段 unique 值範圍 例如 ecif bae  聚合函數對一組值計算後返回單個值。除了count(統計項數)函數以外,其他的聚合函數在計算式都會忽略空值(null)。所有的聚合函數均為確定性函數。即任何時候使用一組相同的輸入值調用聚合函數執行後

SQL Server進階(七)集合運算

nbsp 分享圖片 src 函數 server -c 計算 lec 括號 概述 為什麽使用集合運算:   在集合運算中比聯接查詢和EXISTS/NOT EXISTS更方便。 並集運算(UNION) 並集:兩個集合的並集是一個包含集合A和B中所有元素的集合。

SQL Server聚合函數與聚合開窗函數

char 數值 單個 分享圖片 都是 數據類型 代碼 值調用 sum 以下面這個表的數據作為示例。 什麽是聚合函數? 聚合函數:聚合函數就是對一組值進行計算後返回單個值(即分組)。聚合函數在計算時都會忽略空值(null)。 所有的聚合函數均為確定性函數。即任何時候使用一組

SQL Server聚合函式與聚合開窗函式

以下面這個表的資料作為示例。 什麼是聚合函式? 聚合函式:聚合函式就是對一組值進行計算後返回單個值(即分組)。聚合函式在計算時都會忽略空值(null)。 所有的聚合函式均為確定性函式。即任何時候使用一組相同的輸入值呼叫聚合函式執行後的返回值都是相同的,無二義性。 COUNT(統計函式):COUNT

SQL Server效能優化案例分享(1)——CPU持續過高——CPU高使用率的常見原因及處理方向

本系列屬於 SQL Server效能優化案例分享 專題     部分內容借用《SQL Server 2012實施與管理實戰指南》P592,如果SQL Server錯誤日誌裡面並沒有17883/17884這類錯誤,但是SQ

SQL Server On Linux(2)——SQL Server 2019 For Linux安裝過程細節研究

  接上文SQL Server On Linux(1)——CentOS 7 安裝SQL Server2019 在安裝過程中,作者發現了一些資訊,這些資訊引起了作者的興趣,那麼下面作者把自己研究的結果分享出來,如果讀者對此有深入研究過,歡迎指正。 為什麼要研究這些東西?說白了就

SQL SERVER效能優化SQL

sql server 效能優化方法 --檢視是否有死鎖 dECLARE  @tab TABLE(NAME varchar(100),value varchar(200)); INSERT INTO @tab EXEC('DBCC OPENTRAN WITH TABLERESULTS

SQL Server資料庫————模糊查詢和聚合函式

***********模糊查詢*********/ 關鍵字: like (!!!!字串型別) in (,,)  匹配()內的某個具體值(括號裡可以寫多個值) between... and.. 在某兩個值的區間範圍中(前後都包括,小的寫前面,大的寫後面)   *****

sql server 2016新特性 查詢儲存(Query Store)的效能影響

前段時間給客戶處理效能問題,遇到一個新問題, 客戶的架構用的是 alwayson ,並且硬體用的是4路96核心,記憶體1T ,全固態快閃記憶體盤,sql server 2016 。 問題  描述        客戶經常出現系統卡住的現象,從當時跟蹤的語句執行情況看  是補卡住了,但每次的阻塞源頭都不一樣,當

Sql Server效能優化輔助指標SET STATISTICS TIME ON和SET STATISTICS IO ON

1.前言         對於優化SQL語句或儲存過程,以前主要是用如下語句來判斷具體執行時間,但是SQL環境是複雜多變的,下面語句並不能精準判斷效能是否提高;如果需要精確知道CPU、IO等資訊,就無能為力了。 PRINT convert(varch

SQL CHECK sql server免費監控單例項工具 SQL Check 一款實時效能監測工具

SQL Check 閱讀目錄 SQL Check? 主要特點 說說不足 下載地址 小結 一款實時效能監測工具 回到目錄 SQL Check?

SQL Server 執行T-SQL提示:將截斷字串或二進位制資料[SQLSTATE 22001] (錯誤 8152)

今天在執行以前寫的將增量同步到全量的作業過程中報如下錯誤: 訊息 已以使用者 NT SERVICE\SQLSERVERAGENT 的身份執行。 將截斷字串或二進位制資料。 [SQLSTATE 22001] (錯誤 8152) 語句已終止。 [SQLSTATE 01000] (錯誤 36

SSIS最佳實踐:SQL Server提升執行效能

SQL Server整合服務(SQL Server Integration Services,SSIS)在其前輩DTS(Data Transformation Services,資料轉換服務)的基礎上進步了不少,從可用性、效能和並行等方面來說,它已經成長為一個企業級ETL(Extractio