国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 開(kāi)發(fā) > 綜合 > 正文

堆表上的轉(zhuǎn)發(fā)記錄

2024-07-21 02:46:38
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
堆表上的轉(zhuǎn)發(fā)記錄

今天這篇文章我想談下堆表上特有的性能問(wèn)題:轉(zhuǎn)發(fā)記錄(Forwarding Records)。首先我們要澄清下什么是堆表:堆表就是沒(méi)有聚集索引定義的表。它對(duì)插入新記錄非常快,但當(dāng)你讀取數(shù)據(jù)時(shí)非常慢。讀取數(shù)據(jù)會(huì)在你的存儲(chǔ)子系統(tǒng)上引入隨機(jī)存取(random I/O),有時(shí)候當(dāng)你碰到轉(zhuǎn)發(fā)記錄,它會(huì)進(jìn)一步降低你的讀取性能。

為什么會(huì)有轉(zhuǎn)發(fā)記錄?

當(dāng)堆表里的記錄需要移動(dòng)到不同的物理位置時(shí),SQL Server使用轉(zhuǎn)發(fā)記錄。假設(shè)你有一個(gè)變長(zhǎng)列的表,首先你在堆表里插入一些記錄,這個(gè)時(shí)候你沒(méi)有在變長(zhǎng)列里存儲(chǔ)任何數(shù)據(jù):

 1 -- Create a table to demonstrate forwarding records 2 CREATE TABLE HeapTable 3 ( 4     Col1 INT IDENTITY(1, 1), 5     Col2 CHAR(2000), 6     Col3 VARCHAR(1000) 7 ) 8 GO 9 10 -- Insert 4 records - those will fit into one page11 INSERT INTO HeapTable VALUES12 (13     REPLICATE('1', 2000),14     ''15 ),16 (17     REPLICATE('2', 2000),18     ''19 ),20 (21     REPLICATE('3', 2000),22     ''23 ),24 (25     REPLICATE('4', 2000),26     ''27 )28 GO

當(dāng)你在變長(zhǎng)列執(zhí)行UPDATE語(yǔ)句時(shí),想象下會(huì)發(fā)生什么?在那個(gè)情況下SQL Server可能需要擴(kuò)展這個(gè)記錄,因?yàn)橛涗洿笮「L(zhǎng)了,其他記錄必須從同個(gè)數(shù)據(jù)頁(yè)移走。

1 -- Let's update the table and expand each row of the table2 UPDATE HeapTable3 SET Col3 = REPLICATE('5', 1000)4 GO

在那個(gè)情況下,SQL Server在原始位置留下稱為轉(zhuǎn)發(fā)記錄,它指向記錄最終存儲(chǔ)的新位置。

SQL Server需要使用這個(gè)方法來(lái)避免更新同個(gè)表上所有非聚集索引。你可能知道,當(dāng)你在堆表上創(chuàng)建非聚集索引時(shí),在葉子層,非聚集索引指向記錄數(shù)據(jù)存儲(chǔ)的物理位置。沒(méi)有抓發(fā)記錄的話,所有這些指針都要改變,這會(huì)大幅度降低你的性能。

如何修正轉(zhuǎn)發(fā)記錄?

為了找出表里是否包含轉(zhuǎn)發(fā)記錄,你可以使用DMFsys.dm_db_index_physical_stats。當(dāng)你在堆表上調(diào)用這個(gè)函數(shù)并傳入DETAILED模式,SQL Server通過(guò)forwarded_record_count列告訴你表上的轉(zhuǎn)發(fā)記錄數(shù)。

 1 -- Check the forwarding record count through sys.dm_db_index_physical_stats 2 SELECT 3     index_type_desc, 4     page_count,  5     avg_page_space_used_in_percent, 6     avg_record_size_in_bytes, 7     forwarded_record_count 8 FROM sys.dm_db_index_physical_stats 9 (10     DB_ID('ALLOCATIONDB'), 11     OBJECT_ID('HeapTable'),12     NULL, 13     NULL, 14     'DETAILED'15 )16 GO

可以看到,表上有2條轉(zhuǎn)發(fā)記錄,在4條記錄之外。為了去掉這些轉(zhuǎn)發(fā)記錄,你可以重建表。

1 -- Rebuild the heap table to get rid of the Forwarding Records2 ALTER TABLE HeapTable REBUILD3 GO

再次運(yùn)行剛才的查詢,你會(huì)發(fā)現(xiàn)轉(zhuǎn)發(fā)記錄已經(jīng)消失。

 1 -- Check the forwarding record count through sys.dm_db_index_physical_stats 2 SELECT 3     index_type_desc, 4     page_count,  5     avg_page_space_used_in_percent, 6     avg_record_size_in_bytes, 7     forwarded_record_count 8 FROM sys.dm_db_index_physical_stats 9 (10     DB_ID('ALLOCATIONDB'), 11     OBJECT_ID('HeapTable'),12     NULL, 13     NULL, 14     'DETAILED'15 )16 GO

DBA總會(huì)考慮到索引碎片,索引重建和索引重新組織操作。但沒(méi)有人想過(guò)堆表里的轉(zhuǎn)發(fā)記錄。如果你維護(hù)數(shù)據(jù)庫(kù),經(jīng)常檢查下堆表上的轉(zhuǎn)發(fā)記錄數(shù),保證始終有最好的性能,這是個(gè)非常好的想法。

小結(jié)

在這個(gè)文章里你看到了堆表上轉(zhuǎn)發(fā)記錄是咋樣,它是如何降低的記錄讀取,因?yàn)樾枰~外的邏輯讀。當(dāng)我為數(shù)據(jù)庫(kù)進(jìn)行健康檢查時(shí),我在檢查堆表時(shí),總會(huì)看下轉(zhuǎn)發(fā)記錄數(shù)。

相信我:數(shù)據(jù)庫(kù)里會(huì)有巨大數(shù)量的堆表,在生產(chǎn)系統(tǒng)里也會(huì)有很多轉(zhuǎn)發(fā)記錄,但DBA們并沒(méi)意識(shí)到這個(gè)副作用。作為第一經(jīng)驗(yàn),我經(jīng)常推薦在表上建立聚集索引來(lái)避免轉(zhuǎn)發(fā)記錄。當(dāng)然在一些特定場(chǎng)景里,例如最后頁(yè)插入加鎖競(jìng)爭(zhēng)(Last Page Insert Latch Contention),在這里你可以使用堆表來(lái)避免這個(gè)問(wèn)題,但大多數(shù)情況下,在表上建立聚集索引還是非常有用的。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 宝应县| 青州市| 思南县| 正镶白旗| 增城市| 邯郸市| 夹江县| 珠海市| 凭祥市| 贡山| 昔阳县| 商城县| 横山县| 布尔津县| 毕节市| 揭西县| 临邑县| 桦甸市| 鲁山县| 鄂托克前旗| 镇平县| 普洱| 集贤县| 拉萨市| 鄂托克旗| 灌南县| 资溪县| 龙山县| 中西区| 广宁县| 峨眉山市| 营山县| 平远县| 阜宁县| 乌苏市| 电白县| 龙山县| 甘洛县| 长宁区| 汝州市| 丰都县|