मेरे पास एक उत्पादन डेटाबेस में एक तालिका है जिसका आकार 525 जीबी है, जिसमें से 383 जीबी अप्रयुक्त है:
मैं इस स्पेस में से कुछ को पुनः प्राप्त करना चाहूंगा, लेकिन, उत्पादन डीबी के साथ खिलवाड़ करने से पहले, मैं कम डेटा वाले टेस्ट डीबी में एक समान टेबल पर कुछ रणनीतियों का परीक्षण कर रहा हूं। इस तालिका में एक समान समस्या है:
तालिका के बारे में कुछ जानकारी:
- भरण कारक 0 पर सेट है
- लगभग 30 कॉलम हैं
- स्तंभों में से एक LOB प्रकार की छवि है, और यह उन फ़ाइलों को संग्रहीत कर रहा है जो आकार में कुछ KB से लेकर कई सौ MB तक होती हैं
- तालिका में इससे संबंधित कोई काल्पनिक सूचकांक नहीं है
सर्वर SQL Server 2017 (RTM-GDR) (KB4505224) - 14.0.2027.2 (X64) चला रहा है। डेटाबेस SIMPLE
पुनर्प्राप्ति मॉडल का उपयोग कर रहा है ।
कुछ चीजें जो मैंने कोशिश की हैं:
- अनुक्रमणिका का पुनर्निर्माण करना
ALTER INDEX ALL ON dbo.MyTable REBUILD
:। इसका नगण्य प्रभाव पड़ा। - अनुक्रमणिका का पुनर्गठन
ALTER INDEX ALL ON dbo.MyTable REORGANIZE WITH(LOB_COMPACTION = ON)
:। इसका नगण्य प्रभाव पड़ा। LOB स्तंभ को किसी अन्य तालिका में कॉपी किया गया, स्तंभ को गिरा दिया, स्तंभ को फिर से बनाया, और डेटा को वापस कॉपी किया (जैसा कि इस पोस्ट में उल्लिखित है: मुक्त अप्रयुक्त स्थान SQL सर्वर तालिका )। यह अप्रयुक्त स्थान को कम कर देता है, लेकिन ऐसा लगता है कि इसे केवल उपयोग किए गए स्थान में परिवर्तित करना है:
तालिका को निर्यात करने के लिए bcp उपयोगिता का उपयोग किया, इसे छोटा किया और इसे पुनः लोड किया (जैसा कि इस पोस्ट में उल्लिखित है: तालिका के लिए अप्रयुक्त स्थान को कैसे मुक्त किया जाए )। इसने अप्रयुक्त स्थान को भी कम कर दिया और उपयोग की गई जगह को उपरोक्त छवि के समान हद तक बढ़ा दिया।
- हालांकि इसकी अनुशंसा नहीं की गई है, मैंने DBCC SHRINKFILE और DBCC SHRINKDATABASE कमांड की कोशिश की, लेकिन उनका अप्रयुक्त स्थान पर कोई प्रभाव नहीं पड़ा।
- दौड़ने से
DBCC CLEANTABLE('myDB', 'dbo.myTable')
कोई फर्क नहीं पड़ा - मैंने छवि और पाठ डेटाटिप्स को बनाए रखने के बाद और डेटाटाइप्स को परिवर्तनशील (अधिकतम) और varchar (अधिकतम) में परिवर्तित करने के दौरान उपरोक्त दोनों की कोशिश की है।
- मैंने एक नए डेटाबेस में डेटा को एक नई तालिका में आयात करने की कोशिश की, और यह केवल अप्रयुक्त स्थान को उपयोग किए गए स्थान में परिवर्तित कर दिया। मैंने इस पोस्ट में इस प्रयास के विवरण को रेखांकित किया है ।
मैं उत्पादन DB पर ये प्रयास नहीं करना चाहता अगर ये वे परिणाम हैं जो मैं उम्मीद कर सकता हूं, तो:
- इन प्रयासों में से कुछ के बाद भी अप्रयुक्त स्थान का उपयोग किए गए स्थान में परिवर्तित क्यों किया जा रहा है? मुझे ऐसा लगता है कि मुझे इस बात की अच्छी समझ नहीं है कि हुड के नीचे क्या हो रहा है।
- क्या इस्तेमाल की गई जगह को बढ़ाए बिना अप्रयुक्त स्थान को कम करने के लिए मैं कुछ और कर सकता हूं?
संपादित करें: यहां डिस्क उपयोग रिपोर्ट और तालिका के लिए स्क्रिप्ट है:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[MyTable](
[Column1] [int] NOT NULL,
[Column2] [int] NOT NULL,
[Column3] [int] NOT NULL,
[Column4] [bit] NOT NULL,
[Column5] [tinyint] NOT NULL,
[Column6] [datetime] NULL,
[Column7] [int] NOT NULL,
[Column8] [varchar](100) NULL,
[Column9] [varchar](256) NULL,
[Column10] [int] NULL,
[Column11] [image] NULL,
[Column12] [text] NULL,
[Column13] [varchar](100) NULL,
[Column14] [varchar](6) NULL,
[Column15] [int] NOT NULL,
[Column16] [bit] NOT NULL,
[Column17] [datetime] NULL,
[Column18] [varchar](50) NULL,
[Column19] [varchar](50) NULL,
[Column20] [varchar](60) NULL,
[Column21] [varchar](20) NULL,
[Column22] [varchar](120) NULL,
[Column23] [varchar](4) NULL,
[Column24] [varchar](75) NULL,
[Column25] [char](1) NULL,
[Column26] [varchar](50) NULL,
[Column27] [varchar](128) NULL,
[Column28] [varchar](50) NULL,
[Column29] [int] NULL,
[Column30] [text] NULL,
CONSTRAINT [PK] PRIMARY KEY CLUSTERED
(
[Column1] ASC,
[Column2] ASC,
[Column3] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[MyTable] ADD CONSTRAINT [DF_Column4] DEFAULT (0) FOR [Column4]
GO
ALTER TABLE [dbo].[MyTable] ADD CONSTRAINT [DF_Column5] DEFAULT (0) FOR [Column5]
GO
ALTER TABLE [dbo].[MyTable] ADD CONSTRAINT [DF_Column15] DEFAULT (0) FOR [Column15]
GO
ALTER TABLE [dbo].[MyTable] ADD CONSTRAINT [DF_Column16] DEFAULT (0) FOR [Column16]
GO
मैक्स वर्नोन के उत्तर में कमांड निष्पादित करने के परिणाम इस प्रकार हैं:
╔════════════╦═══════════╦════════════╦═════════════════╦══════════════════════╦════════════════════╗
║ TotalBytes ║ FreeBytes ║ TotalPages ║ TotalEmptyPages ║ PageBytesFreePercent ║ UnusedPagesPercent ║
╠════════════╬═══════════╬════════════╬═════════════════╬══════════════════════╬════════════════════╣
║ 9014280192║ 8653594624║ 1100376║ 997178 ║ 95.998700 ║ 90.621500 ║
╚════════════╩═══════════╩════════════╩═════════════════╩══════════════════════╩════════════════════╝
╔═════════════╦═══════════════════╦════════════════════╗
║ ObjectName ║ ReservedPageCount ║ UsedPageCount ║
╠═════════════╬═══════════════════╬════════════════════╣
║ dbo.MyTable ║ 5109090 ║ 2850245 ║
╚═════════════╩═══════════════════╩════════════════════╝
अपडेट करें:
मैक्स वर्नोन द्वारा सुझाए गए अनुसार मैंने निम्न भाग किया:
DBCC UPDATEUSAGE (N'<database_name>', N'<table_name>');
और यहाँ उत्पादन था:
DBCC UPDATEUSAGE: Usage counts updated for table 'MyTable' (index 'PK_MyTable', partition 1):
USED pages (LOB Data): changed from (568025) to (1019641) pages.
RSVD pages (LOB Data): changed from (1019761) to (1019763) pages.
इसने तालिका के लिए डिस्क उपयोग को अद्यतन किया:
और समग्र डिस्क उपयोग:
तो, ऐसा लगता है कि समस्या यह थी कि SQL सर्वर द्वारा ट्रैक किए गए डिस्क उपयोग वास्तविक डिस्क उपयोग के साथ बेतहाशा आउट-सिंक हो गए थे। मैं इस मुद्दे को हल करने पर विचार करूंगा, लेकिन मुझे यह जानने में दिलचस्पी होगी कि यह पहली जगह में क्यों हुआ होगा!
DBCC UPDATEUSAGE
अप्रयुक्त स्थान और अप्रयुक्त पृष्ठ गणना को अद्यतन किया। ऐसा लगता है कि SQL सर्वर द्वारा रिपोर्ट की जा रही डिस्क का उपयोग और पृष्ठ की जानकारी सिंक से बहुत बाहर थी - मैंने विवरण के साथ अपनी पोस्ट को अपडेट किया। मैं इस बारे में उत्सुक हूं कि यह पहली बार में कैसे हुआ होगा, लेकिन कम से कम समस्या पाई गई। आपकी सभी मदद के लिए धन्यवाद, मैं वास्तव में इसकी सराहना करता हूं!