SQLServer中間接實現函數索引或者Hash索引

来源:http://www.cnblogs.com/wy123/archive/2017/03/26/6617700.html
-Advertisement-
Play Games

本文出處:http://www.cnblogs.com/wy123/p/6617700.html SQLServer中沒有函數索引,在某些場景下查詢的時候要根據欄位的某一部分做查詢或者經過某種計算之後做查詢,如果使用函數或者其他方式作用在欄位上之後,就會限制到索引的使用,不過我們可以間接地實現類似於 ...


 

本文出處:http://www.cnblogs.com/wy123/p/6617700.html 

 

SQLServer中沒有函數索引,在某些場景下查詢的時候要根據欄位的某一部分做查詢或者經過某種計算之後做查詢,
如果使用函數或者其他方式作用在欄位上之後,就會限制到索引的使用,不過我們可以間接地實現類似於函數索引的功能。
另外一個就是如果查詢欄位較大或者欄位較多的時候,所建立的索引就顯得有點笨重,效率也不高,
就需要考慮使用一個較小的"替代性"欄位做等價替換,類似於Hash索引,
本文粗淺地介紹兩種上述兩種問題的解決方式,僅供參考。

 

1,在計算列上建索引,實現“函數索引”的功能

  SQLServer在建表的時候允許使用計算列,可以藉助這個計算列來實現函數索引的功能,這裡舉例說明一下

Create Table TestFunctionIndex
(
    id int identity(1,1),
    val varchar(50),
    subval as LOWER(SUBSTRING(val,10,4)) persisted --增加一個持久化計算列
)
GO

--在持久化計算列上建立索引
create index idx_subvar on TestFunctionIndex(subval)
GO

--插入10W行測試數據
insert into TestFunctionIndex(val) values (NEWID())
go 100000

在有索引的欄位上使用函數之後,是無法使用索引的

  如果直接在計算列上查詢,就可以正常地使用到索引了

  

  以上通過在計算列上建立一個索引,可以根據計算列上的索引做查找,避免了直接在欄位上使用函數或者其他操作,造成即便欄位上有索引也用不到的情況

  補充:
  測試中神奇地發現,如果計算列欄位上建立了索引,在原始欄位上使用函數與計算列的函數一樣的時候,可以神奇地使用到計算列上的索引
  可見SQLServer在我們沒有註意的地方也是下了不少功夫的啊

  

 

 

2,生成較長欄位或者多個欄位的Hash值替代原始欄位做查詢或者連接來提升查詢效率

  開發中遇到另外一種常見的情況是經常使用到的查詢條件欄位較長,或者是表連接的時候連接條件欄位較多,
  即便是欄位或者查詢條件上有索引,但是因為欄位較長或者條件較多,此時有可能會影響到查詢的效率
  這種情況就適當考慮將原始的較長的欄位生成一個較小的欄位(但是要確保唯一性),或者是講多個欄位生成一個較短的數據類型做替代,以提高查詢的效率

  舉個例子,假如有這麼一張表,Name欄位是我模擬出來的,Name是一個比較長的欄位,又要用來做檢索
  意思就是查詢欄位較長,索引代價太大,此時就需要考慮用一種較小的等價欄位來替代
  下麵通過某種方式計算較長欄位的Hash值,來做等價替換

  

  模擬生成一下測試數據

Create table testHashColumn
(
    id int identity(1,1),
    QueryName nvarchar(100),
    HashName AS CAST( HASHBYTES('MD2',QueryName)  AS UNIQUEIDENTIFIER) persisted
)
GO

create index idx_HashName ON testHashColumn(HashName)
GO

--這裡模擬生成一個較長的名字欄位
DECLARE @i int = 0
while @i<10000
begin 
    INSERT INTO testHashColumn (QueryName) VALUES (CONCAT('北京新視點科技文化傳媒有限公司',@i))
    set @i = @i+1
end

我們知道,Name這個名字是nvarchar(100)的,這個欄位做索引不是不可以,
如果情況複雜,實際中有可能比這個欄位更大,做索引顯得太寬了,造成索引空間過大,在效率上有一定程度的影響。

這裡就可以考慮在Name這個欄位上生成一個“替代”欄位(上述HashName AS CAST( HASHBYTES('MD2',QueryName) AS UNIQUEIDENTIFIER) persisted這個計算列),

這個欄位首選是要跟實際值一一對應的,另外就是要求“替代”的欄位類型要求相對較小,
當然方法也有多種,比如生成利用checksum函數生成一個校驗值,
但是據實際觀察checksum生成的校驗值是有可能重覆的,也就是說兩個不同的字元串,生成同一個校驗值
比如這樣,很容易驗證出來這個問題,可以認為是對於不同的字元串,計算之後得到同一個校驗和

  因此在生成“替代”欄位的時候,需要考慮計算值的唯一性
  這裡使用的是HASHBYTES加密函數,對字元串加密,然後對加密之後的數據生成一個UNIQUEIDENTIFIER,重覆的概率就小的多的多了
  演示這裡通過CAST( HASHBYTES('MD2','北京新視點科技文化傳媒有限公司999') AS UNIQUEIDENTIFIER)的方式,就可以給這個較長的欄位生成一個UNIQUEIDENTIFIER類型的欄位,
  當然也不一定只有這一種方法,甚至可以做的跟複雜,只要能保證一個唯一的長欄位生成的較短的欄位也是唯一的就可以達到目的了
  參考如下查詢,就可以使用HashName計算出來的值與計算列做比較,在一定程度上可以減少檢索欄位索引的大小,又能達到目的的效果

   如截圖,就可以使用HashName欄位上的索引了,同時也避免了在原始的QueryName這個較長的欄位上建索引,節約了空間並提高了查詢效率

 

3, 邏輯主鍵為多個欄位的時候,在多了欄位上生成一個“替代”性的唯一欄位

  某些情況下業務需求或者設計也好(比如沒有達到第三範式,BC範式,第四範式,甚至是第五範式),在表連接的時候往往會有多個欄位
  比如這種樣子:

SELECT *
FROM TableNameA a
INNER JOIN TableNameB b
    ON a.key=b.key
        AND a.Type = b.Type
        AND a.Status = b.Staus
        AND a.CreationTime = b.CreationTime
        AND a.***=b.***
where ***

    在表關聯的時候,連接條件很多,
  如果是這樣子,最好的情況就是建立一個較寬的複合索引,
  但是這樣的話,索引的寬度和體積就變得很大,使用的時候效率也有一定的影響
  這種情況就可以考慮在TableNameA 和 TableNameB 上,
  利用多個連接的欄位(Key+Type +Status +CreationTime+***)做了類似於示例2中的一個計算列,在計算列上建立一個索引
  然後再表連接的時候就可以用如下的方式替代

SELECT *
FROM TableNameA a
INNER JOIN TableNameB b
    ON a.HashValue=b.HashValue
WHERE ***

  總是,這是一種以空間換時間的思路(冗餘存儲一個類似於標識符的欄位,提高查詢效率),
  在生成“替代”欄位的思想有兩點,第一要足夠的小,第二要原始值生成替代欄位的唯一性

 


總結:SQLServer 中沒有函數索引和Hash索引,而某些業務需求或者說是為了性能考慮,又需要類似的功能,
   通過類似於空間換時間的方法來實現,可以變通地來實現類似於函數索引或者Hash索引的功能,已達到其他資料庫中函數索引和Hash索引的效果(雖然原理可能不一樣)。
   需要註意的就是在生成計算列或者說Hash值替代的時候要註意計算方式,確保生成之後的Key值的唯一性
   當然實現方式就可以根據需要自行選擇了,條條大路通羅馬。

  

 


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

-Advertisement-
Play Games
更多相關文章
  • 有一個Button 按鈕,要想為該按鈕設置onClick事件和OnTouch事件 此時,我們現在分析一下,是onTouch先執行,還是onClick執行,接下來我從FrameWork 源碼去探尋一下整個事件的執行流程和原理: 我們知道 Button ,TextView 等基礎控制項的基類都是View, ...
  • 主要原理:是在主界面有兩個空間,一個是EditText,一個是ListView,ListView是放在EditText下麵的,然後自定義建立一個adapter適配器, 這個適配器要繼承Filterable這個介面,並實現這個介面的兩個方法,一個是過濾方法,一個是過濾後的方法,一般我們是在過濾方法裡面 ...
  • Android原生的CalendarView根本無法滿足我們日常開發的需要,在開發吾記APP的過程中,我覺得需要來一款高性能且美觀簡潔的日曆控制項,覺得魅族的日曆風格十分適合,於是打算擼一款。 github地址:https://github.com/huanghaibin-dev/CalendarVi ...
  • 想獲取用戶各項行為數據嗎? 想輕鬆查看用戶行為圖表嗎? 想高效進行 App 運營管理嗎? 想,來我帶你玩轉 App 數據統計。這裡我使用專業、輕便的 "JAnalytics" 。 本文內容分為兩部分:代碼示例&使用技巧部分、控制台圖表查看部分。 代碼示例&使用技巧 集成 1. 下載 "JAnalyt ...
  • 本文並非最終版本,如果想要關註更新或更正的內容請關註文集,聯繫方式詳見文末,如有疏忽和遺漏,歡迎指正。 本文相關目錄: ================== 所屬文集: "【iOS】07 設備工具 " ================== "7.4 定位服務 1.0 簡介" "7.4 定位服務 2. ...
  • Context,中文直譯為“上下文”,SDK中對其說明如下: 1、它描述的是一個應用程式環境的信息,即上下文。 2、該類是一個抽象(abstract class)類,Android提供了該抽象類的具體實現類。 3、通過它我們可以獲取應用程式的資源和類,也包括一些應用級別操作,例如:啟動一個Activ ...
  • 轉載請註明出處:http://www.cnblogs.com/cnwutianhao/p/6611252.html 引言:項目開發有時會使用上傳文件到伺服器,再從伺服器取數據顯示到本地這一過程;或者輸入一段文字,再把文字顯示出來。這個過程都用到了IO流。 IO流分為字元流(Reader\Writer ...
  • 最近公司開發一個項目,要求app能夠發送簡訊並獲取送達報告。這本不是一個什麼難題,實現這一功能的代碼一搜一大把,那麼這麼簡單的一個問題,為什麼我要在這裡提出來呢?那是因為我在寫代碼的時候掉入了一個坑,而且這很可能發生在很多和我一樣粗心的朋友身上。先給大家分享一下當初讓我掉進坑裡的代碼: 咋一看,好像 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...