簡體   English   中英

Sql Server舊數據庫到群集索引與否

[英]Sql Server Legacy Database To Clustered index or not

我們有一個遺留數據庫,它是一個sql server db(2005和2008)。

表中的所有主鍵都是UniqueIdentifiers。

這些表當前沒有在它們上創建聚集索引,我們在僅有750k記錄的表上遇到性能問題。 這是我使用唯一標識符作為唯一主鍵的第一個數據庫,我從未見過sql server返回數據這么慢。

我不想在uniqueidentifier上創建聚簇索引,因為它們不是順序的,因此在插入數據時會降低應用程序的速度。

我們無法刪除uniqueidentifier,因為它用於遠程站點記錄身份管理目的。

我曾考慮過向表中添加一個大整數標識列,並在此列上創建聚簇索引並包含唯一標識符列。

int identity - 保持插入速度唯一標識符的第一列 - 確保應用程序按預期保持工作。

目標是改進身份查詢並加入表查詢性能。

問題1:這會改善數據庫的查詢性能還是會降低它的速度?

Q2:有沒有我沒有列出的替代方案?

謝謝皮特

編輯:性能問題是通過select語句快速檢索數據,特別是如果一些更“交易/更改”的表連接在一起。

編輯2:表之間的連接通常都在主鍵和外鍵之間,對於具有外鍵的表,它們包含在非聚集索引中以提供更多覆蓋索引。

這些表都沒有其他值可以提供良好的聚簇索引。

我更傾向於在每個高負載表上添加一個額外的標識列,然后在聚簇索引中包含當前的Guid PK列以提供最佳的查詢性能。

編輯3:我估計只有80%的查詢是通過數據訪問機制單獨在主鍵和外鍵上執行的。 通常,我們的數據模型具有延遲加載的對象,這些對象在訪問時執行查詢,這些查詢使用對象id和PK列。 我們有大量用戶驅動的數據排除/包含查詢,它們使用外鍵列作為基於類型X的條件的過濾器,不包括以下id。 剩下的20%是Enum(int)或日期范圍列的子句,在系統中執行的文本查詢非常少。

在可能的情況下,我已經添加了覆蓋索引來覆蓋最重的查詢,但到目前為止,我仍然感到失望。 藍腳表示數據存儲為堆。

如果表上沒有聚簇索引,則將其存儲為堆而不是b樹。 堆數據訪問在SQL Server中絕對是非常糟糕的,因此您肯定需要添加聚簇索引。

我同意您的分析,GUID列是群集的不良選擇,尤其是因為您無法使用NEWSEQUENTIALID()。 如果您願意,可以創建一個新的人工整數鍵,但如果有另一列或列組合作為聚簇索引有意義,那也沒關系。

您是否有經常用於范圍掃描的字段? 哪些列用於連接? 是否有一個列的組合,除了GUID之外還唯一標識行? 發布數據模型的樣本將有助於我們建議一個良好的聚類候選者。

我不確定您的GUID來自哪里,但如果它們是在插入期間生成的,則使用SQL Server中的NEWSEQUENTIALID()而不是NEWID()將幫助您避免插入期間的碎片問題。

關於聚集索引的選擇,正如Kimberly L. Tripp 在此所述 :“選擇聚簇索引的最重要因素是它是唯一的,狹窄的和靜態的(不斷增加的其他優點是最小化分裂)。” 與INT或甚至BIGINT相比,GUID不能滿足狹窄的要求。

Kimberly還有一篇關於GUID作為PRIMARY KEYs和/或聚類鍵的優秀文章。

對我來說,這不是100%明確的:您是通過GUID或其他列查詢表的第一個訪問模式嗎? 當加入其他表時,最常使用哪些列(和數據類型)?

在我更了解如何使用這些GUID之前,我無法給你任何可靠的建議。 我意識到你說它們是主鍵,但這並不能保證它們被用作查詢或連接的主要條件。

UPDATE

現在我知道了一點,我有一個瘋狂的建議。 在GUID上對這些表進行聚類,但將填充因子設置為60%。 這將改善頁面拆分問題,並為您提供更好的查詢這些小狗的性能。

至於使用Guid.NewGuid(),似乎你可以在C#中執行sequentialGUIDs。 我在SO上找到了以下代碼:

[DllImport("rpcrt4.dll", SetLastError = true)]
static extern int UuidCreateSequential(out Guid guid);

public static Guid SequentialGuid()
{
    const int RPC_S_OK = 0;
    Guid g;
    if (UuidCreateSequential(out g) != RPC_S_OK)
        return Guid.NewGuid();
    else
        return g;
}

newsequentialID()實際上只是UuidCreateSequential的包裝器。 我敢肯定,如果你不能直接在客戶端使用它,你可以找到一種方法快速往返服務器從那里獲得一個新的順序ID,甚至可能使用“分配器”表和存儲過程來完成這項工作。

您沒有說明您的性能問題。 如果執行效果最差的操作是INSERT,那么您的解決方案可能是正確的。 如果它是其他東西,那么我將看看聚集索引如何幫助它。

您可能會查看表上的現有索引以及使用它們的查詢。 您可以選擇一個索引,雖然稍微降低INSERT,但會為當前的性能問題區域提供更大的好處。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM