SQL索引碎片的產生,處理過程。

来源:https://www.cnblogs.com/adsoft/archive/2019/11/28/11950693.html
-Advertisement-
Play Games

本文參考 https://www.cnblogs.com/CareySon/archive/2011/12/22/2297568.html https://www.jb51.net/softjc/126055.html https://docs.microsoft.com/zh-cn/sql/rel ...


本文參考

https://www.cnblogs.com/CareySon/archive/2011/12/22/2297568.html

https://www.jb51.net/softjc/126055.html

https://docs.microsoft.com/zh-cn/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql?view=sql-server-ver15

本文需要對“索引”和MSSQL中數據的“存儲方式”有一定瞭解。

軟體經常在使用一段時間過後會無緣無故卡頓,這是因為在資料庫(MSSQL)頻繁的插入和更新的操作過程中會產生分頁,在分頁的過程中產生碎片導致的。所以,對於碎片需要定時的處理。基本上所有的辦法都是基於對索引的重建和整理,只是方式不同。

  1. 刪除索引並重建
  2. 使用DROP_EXISTING語句重建索引
  3. 使用ALTER INDEX REBUILD語句重建索引
  4. 使用ALTER INDEX REORGANIZE

以上方式各有優缺點,下麵存儲過程主要使用3,4

先看一個整理碎片的存儲過程,然後採用作業的方式定時執行。

Create PROCEDURE [dbo].[proc_rebuild_index]
    @ret    INT OUTPUT
AS
SET NOCOUNT ON
BEGIN
    DECLARE @fldDefragFragment INT = 10;
    DECLARE @fldRebuildFragment INT = 30;
    DECLARE @fldMinPageCount INT = 1000;
    DECLARE @fldTable VARCHAR(256);
    DECLARE @fldIndex VARCHAR(256);
    DECLARE @fldPercent INT;
    DECLARE @Sql       VARCHAR(256);
    declare @DBID  int;
    BEGIN TRY
        SET @ret = -1;
        set @DBID = db_id();
        -- 獲取索引碎片狀況
        DECLARE curIndex CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY FOR
            SELECT 
                 TBL.NAME TABLE_NAME
                ,IDX.NAME INDEX_NAME
                ,AVGP.AVG_FRAGMENTATION_IN_PERCENT
            FROM SYS.DM_DB_INDEX_PHYSICAL_STATS(@DBID, NULL,NULL, NULL, 'LIMITED') AS AVGP 
            INNER JOIN SYS.INDEXES AS IDX 
             ON AVGP.OBJECT_ID = IDX.OBJECT_ID 
            AND AVGP.INDEX_ID = IDX.INDEX_ID 
            INNER JOIN SYS.TABLES AS TBL 
             ON AVGP.OBJECT_ID = TBL.OBJECT_ID
            INNER JOIN SYS.DM_DB_PARTITION_STATS PS
             ON AVGP.OBJECT_ID = PS.OBJECT_ID
            AND AVGP.INDEX_ID = PS.INDEX_ID 
            WHERE
                AVGP.INDEX_ID >= 1 
            AND AVGP.AVG_FRAGMENTATION_IN_PERCENT >= @fldDefragFragment
            AND PS.RESERVED_PAGE_COUNT >= @fldMinPageCount;
        -- 打開游標
        OPEN curIndex;
        -- 獲取游標
        FETCH NEXT FROM curIndex
        INTO @fldTable,@fldIndex,@fldPercent;
        WHILE @@FETCH_STATUS = 0
            BEGIN
                --碎片率大於30,重建索引
                IF @fldPercent >= @fldRebuildFragment
                    BEGIN
                        SET @Sql = 'ALTER INDEX ' + @fldIndex + ' ON ' + @fldTable + ' REBUILD';
                        EXEC(@Sql);
                    END
                ELSE
                --碎片率小於30,重組索引
                    BEGIN
                        SET @Sql = 'ALTER INDEX ' + @fldIndex + ' ON ' + @fldTable + ' REORGANIZE';
                        EXEC(@Sql);
                    END
                -- 獲取游標
                FETCH NEXT FROM curIndex
                INTO @fldTable,@fldIndex,@fldPercent;
            END
        -- 關閉游標
        CLOSE curIndex;
        DEALLOCATE curIndex;
        SET @ret = 0;
    END TRY
    BEGIN CATCH
        SET @ret = -1;
        DECLARE @ErrorMessage    nvarchar(4000);
        DECLARE @ErrorSeverity    int;
        DECLARE @ErrorState        int;
        SELECT
              @ErrorMessage = ERROR_MESSAGE()
            , @ErrorSeverity  = ERROR_SEVERITY()
            , @ErrorState = ERROR_STATE();
        RAISERROR( @ErrorMessage, @ErrorSeverity, @ErrorState);
        RETURN;
    END CATCH;
END

下麵直觀的看一下碎片產生的過程

--創建測試表
if object_id('test') is not null 
  drop table test
go
create table test
(
  col1 int, 
  col2 char(985),
  col3 varchar(10)
)
Go
--創建聚焦索引
create CLUSTERED index cix on test(col1);
go
--插入數據
declare @var int 
set @var=100
while (@var<900) 
begin
  insert into test(col1, col2, col3) 
  values (@var, 'xxx', '')
  set @var=@var+100
end;
--查看頁存儲情況
select page_count, avg_page_space_used_in_percent, record_count,
       avg_record_size_in_bytes, avg_fragmentation_in_percent, fragment_count,
       * from [master].sys.dm_db_index_physical_stats(db_id(), OBJECT_ID('test'), null, null, 'sampled')

 

--然後做更新操作後,繼續查看頁存儲情況。

update test set col3='更新測試' where col1=100

--再次插入數據後查看頁存儲情況
declare @var int 
set @var=100
while (@var<900) 
begin
  insert into test(col1, col2, col3) 
  values (@var, '插入測試', '')
  set @var=@var+100
end;

 

--下麵看下對碎片整理之前和之後的IO
set statistics io on 
select * from test
alter index cix on test rebuild
select * from test 
set statistics io off

 

 明顯的邏輯讀取減少了。從而提高了性能

 

 

 

 


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

-Advertisement-
Play Games
更多相關文章
  • 推薦sql.js——一款純js的sqlite工具。 一、關於sql.js sql.js(https://github.com/kripken/sql.js)通過使用Emscripten編譯SQLite C代碼,將SQLite移植到Webassembly。 它使用存儲在記憶體中的虛擬資料庫文件,因此不會 ...
  • 剛安裝mysql後想通過navicat來連接mysql,發現報錯 1251這個錯誤,不慌。這個很簡單。 首先通過cmd進入mysql。 然後修改密碼規則 ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你 ...
  • 增加 語法: db.collectionName.insert({json對象}); 刪除 語法: db.collection.remove(查詢條件, num); 第二個參數是整數型,代表刪除的個數;預設是0(刪除全部文檔) 修改 語法: db.collection.update(查詢條件,新值) ...
  • 一、Redis簡介 Redis是一款基於key-value的高性能NoSQL資料庫,開源免費,遵守BSD協議。支持string(字元串) 、 hash(哈希) 、list(列表) 、 set(集合) 、 zset(有序集合)等數據結構,除此之外還提供了鍵過期、發佈訂閱、Lua腳本、事務、流水線(Pi ...
  • 索引的正常使用對於軟體的性能至關重要。 可以通過DMV,DMF檢查缺失索引情況。 --獲取缺失索引語句。 SELECT top 100 mid.index_handle, equality_columns, inequality_columns, included_columns, statemen ...
  • 一、加入依賴 com.github.spt-oss spring-boot-starter-data-redis 2.0.7.0 redis依賴二、添加redis.properties配置文件# REDIS (RedisProperties)# Redis資料庫索引(預設為0)spring.redi... ...
  • 註意,本方法是適用於同一區域網下的遠程連接 註意,本方法是適用於同一區域網下的遠程連接 註意,本方法是適用於同一區域網下的遠程連接 首先需要修改mysql資料庫的相關配置,將user表中的host改為%(因為mysql預設的是只能本地訪問,也就是說只能localhost訪問,若需其他人訪問,則要修改 ...
  • 1、首先關閉虛擬機點擊編輯虛擬機設置 2、點擊想要擴容的硬碟點擊擴容 3、增加容量 輸入想增加的容量,因為我本身是30G寫到35G是加了5G不是增加30G.(此處為了演示只增加5G) 4、開啟虛擬機 查看虛擬機當前磁碟掛載情況 fdisk -l 5、選擇磁碟 fdisk /dev/sda 6、查看磁 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...