2010-11-30 17 views
5

बदलने के लिए SQL तालिका प्रदर्शन बदलने के लिए हमें कुछ कॉलम के डेटा प्रकारों को int से bigint में बदलने की आवश्यकता है। दुर्भाग्यवश इनमें से कुछ तालिकाएं बड़ी हैं, लगभग 7-10 मिलियन पंक्तियां (लेकिन व्यापक नहीं)।कॉलम परिवर्तन डेटा प्रकार

ऑर्डर तालिका परिवर्तन कॉलम इन तालिकाओं पर हमेशा के लिए ले रहा है। क्या इसे हासिल करने का कोई तेज तरीका है?

उत्तर

8

संयोग से, मुझे लगभग 3 घंटे पहले कुछ ऐसा ही करना पड़ा। तालिका 35 minute पंक्तियों था, यह काफी व्यापक है, और यह सिर्फ यह करने के लिए हमेशा के लिए ले रहा था:

alter table myTable add myNewColumn int null; 

while 1=1 
begin 
    update top (100000) myTable 
    set 
     myNewColumn = 0 
    where 
     myNewColumn is null; 

    if @@ROWCOUNT = 0 break; 
end 

alter table myTable alter column myNewColumn int not null; 
alter table myTable add constraint tw_def_myNewColumn default (0) for myNewColumn; 

इस बार, alter table:

alter table myTable add myNewColumn int not null default 0; 

यहाँ है कि मैं क्या के साथ जा रहा समाप्त हो गया है बयान निकट-तत्काल थे। अद्यतन बैचों को करने में लगभग 7-8 मिनट (धीमे सर्वर पर) लग गए। मैं अनुमान लगा रहा हूं कि एसक्यूएल सर्वर मूल्यों को बहाल करने के लिए मेरी मूल क्वेरी में पूर्ववत कर रहा था, लेकिन मुझे इसकी शुरुआत होने की उम्मीद नहीं थी।

वैसे भी, आपके मामले में, शायद कुछ ऐसा ही मदद करेगा। आप एक नया बड़ा कॉलम जोड़ने का प्रयास कर सकते हैं, बैचों में नया कॉलम अपडेट कर सकते हैं, फिर उस पर बाधाएं सेट कर सकते हैं।

+0

मुझे कॉलम आकार बदलने और 10 मिलियन + पंक्तियों वाली तालिका में एक नए कॉलम में कॉपी करने के बीच कोई प्रदर्शन अंतर नहीं मिला। –

+0

जिसका मतलब है कि यह दोनों मामलों में धीमा था? – Matt

2

सही कॉलम टाइप और इंडेक्स के साथ अपनी इच्छित नई तालिका बनाएं। (पुरानी तालिका को स्क्रिप्ट करें, और नाम बदलें।)

नई तालिका (कॉलम सूची) में डालें पुराने_टेबल से * चुनें;

old_table old_table_back का नाम बदलें, new_table old_table का नाम बदलें।

नई तालिका पर पुराने सूचकांक बनाएं, पुरानी तालिका पर किसी भी कठिनाई को छोड़ दें और उन्हें नई तालिका पर क्रिएट करें। फिर, आपके rdbms को ऐसा करने के लिए स्क्रिप्ट उत्पन्न करने का कुछ आसान तरीका होगा।

+0

मौजूदा स्तंभ के डेटा प्रकार को बदलने के अलावा कोई तेजी से एक अलग डेटा प्रकार के साथ एक स्तंभ में एक नई तालिका में का चयन कर रहा है? हम प्राथमिक कुंजी कॉलम के लिए ऐसा कर रहे हैं। –

+0

आम तौर पर बहुत तेज़; प्रत्येक पंक्ति का आकार बदलने के बजाय, यह सिर्फ सही आकार की नई पंक्तियां बना रहा है। – tpdi

0

मैं बस कुछ हफ्ते पहले इसमें 639 मीटर पंक्तियों वाली एक तालिका के साथ भाग गया था। मैं एक नई टेबल बनाने और डेटा को "बैचों" में कॉपी करने के लिए समाप्त हुआ। मुख्य सर्वर पर लगभग 2 दिन लग गए और प्रतिकृति ने इसे दोहराने के लिए 3 दिन लग गए। इसके बाद मैंने पुराने विचारों में उपयोग किए गए सभी विचारों और प्रोसेस को संशोधित किया। इसने मुझे कुछ मुद्दों को साफ करने की इजाजत दी, जैसे कि एक कॉलम से छुटकारा पाने के लिए जो मैं नहीं चाहता था और कुछ मामलों में बेहतर इंडेक्स चुन रहा था। सभी डेटा एसक्यूएल को स्थानांतरित करने के बाद, मैंने पुरानी टेबल गिरा दी।

एक गड़बड़, लेकिन अब इसके लिए बुद्धिमान है। यदि सिस्टम लंबे समय तक रहेगा और लाखों पंक्तियों का कोई मौका है तो पहचान प्राथमिक कुंजी के लिए बड़ी चींटियों का उपयोग करें।

1

मैं बस इस मुद्दे पर भाग गया ... इसमें एक 447,732,310 रिकॉर्ड वाला एक टेबल। अगर एक सहकर्मी एक भयानक समाधान के साथ आया, तो केवल एक नई तालिका में डेटा कॉपी करने के लिए लगभग 24 मिनट लग गए, इंडेक्स बनाने के लिए लगभग 40 मिनट।

यहाँ हम क्या किया है:

--Get ntiles of idOrders, split up into 100 groups - 1:20 minutes 
IF(OBJECT_ID('TEMPDB..#x')) IS NOT NULL 
    DROP TABLE #x 

SELECT nt, MIN(idOrder) idOrderMin, MAX(idOrder) idOrderMax 
INTO #X 
FROM (
     SELECT idOrder, NTILE(100) OVER(ORDER BY idOrder) nt 
     FROM (
       SELECT DISTINCT idOrder FROM order_raw_fields 
     ) X 
) Y 
GROUP BY nt 

-- view results 
--SELECT * FROM #x ORDER BY idOrderMin 

-- create new table 
SELECT TOP 0 * 
INTO ORDER_RAW_FIELDS_Intl 
FROM ORDER_RAW_FIELDS 

ALTER TABLE dbo.ORDER_RAW_FIELDS_Intl 
    ALTER COLUMN value nvarchar(500) 

--Build queries 
SELECT 'insert into ORDER_RAW_FIELDS_Intl select * from order_raw_fields 
where idOrder >= ' + CAST(idOrderMIn AS VARCHAR(100)) + ' and idOrder <= ' + CAST(idOrderMax AS varchar) InsertStmt 
    INTO #inserts 
FROM #X 
ORDER BY idOrderMin 

DECLARE insertCursor CURSOR LOCAL FAST_FORWARD FOR 
    SELECT InsertStmt 
    FROM #inserts 

OPEN insertCursor 

-- 24:04 minute execution time to match 
DECLARE @insertStmt NVARCHAR(125) 
FETCH NEXT FROM insertCursor INTO @insertStmt 
WHILE @@FETCH_STATUS = 0 
BEGIN 
    --EXECUTE @insertStmt 
    EXECUTE sp_executesql @[email protected] 

    PRINT 'Execution Complete: ' + @insertStmt 

    FETCH NEXT FROM insertCursor INTO @insertStmt 
END 

CLOSE insertCursor 
DEALLOCATE insertCursor 

-- Add indexes 
-- 21:37 minutes completion time 
ALTER TABLE [dbo].[ORDER_RAW_FIELDS_Intl] ADD CONSTRAINT [PK_ORDER_RAW_FIELDS_Intl] PRIMARY KEY CLUSTERED 
(
    [idRow] ASC, 
    [idOrder] ASC, 
    [remoteFieldName] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 92) ON [PRIMARY] 
GO 

-- 13:45 minutes completion time 
CREATE NONCLUSTERED INDEX [IX_idOrder_remoteFieldName2] ON [dbo].[ORDER_RAW_FIELDS_Intl] 
(
    [idOrder] ASC, 
    [remoteFieldName] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 94) ON [PRIMARY] 
GO 

-- drop table 
TRUNCATE TABLE [dbo].[ORDER_RAW_FIELDS] 
DROP TABLE [dbo].[ORDER_RAW_FIELDS] 

-- renamed new table to old tables's name 
EXEC sp_rename 'ORDER_RAW_FIELDS_Intl', 'ORDER_RAW_FIELDS'; 
संबंधित मुद्दे