sql - कैसे तीन अलग-अलग तालिकाओं में डेटा डालें Parellel




sql-server sql-server-2008 tsql sql-server-2012 (5)

मेरे पास एक संग्रहीत प्रक्रिया है जो रिकॉर्ड के बल्क में डालेंगे, अब समानांतर में 3 तालिकाओं में डेटा सम्मिलित करने की कोई संभावना है;

  • 1 लाख रिकॉर्ड डालने वाली पहली तालिका
  • दूसरी तालिका 15 लाख रिकॉर्ड डालने।
  • तीसरी तालिका 500k रिकॉर्ड डालने

मेरे ज्ञान के अनुसार - प्रक्रिया सम्मिलन एक के बाद एक हो रहा है

तो मैं समानांतर में लोडिंग कैसे लागू कर सकता हूं?


Answers

यह मानते हुए कि आप सभी सम्मिलित करने के लिए एक ही सम्मिलित तिथि मान करना चाहते हैं, जैसा कि दिखाया गया है, दिनांक दिनांक सेट करने के लिए निर्धारित तिथि पैरामीटर को परिभाषित करें

DECLARE @InsertDate as date
SET @InsertDate = GetDate()

उसके बाद, डालें दिनांक पैरामीटर को अपनी सम्मिलित संग्रहित प्रक्रिया में पास करें और उस इनपुट का उपयोग करने के लिए तदनुसार इस संग्रहीत कार्यविधि को अपडेट करें। यह सुनिश्चित करेगा कि एक ही सम्मिलन तिथि मान सभी आवेषण के लिए उपयोग किया जाएगा।

EXEC dbo.InsertTables123 @p1 = @InsertDate

@InsertDate इनपुट पैरामीटर को मैन्युअल रूप से सौंपा जा सकता है यदि आवश्यक हो तो वर्तमान दिनांक के अलावा अन्य


संरचना और सामग्री में समान सभी तीन तालिकाओं हैं? यदि हां, तो व्यवहार / मर्ज प्रतिकृति का उपयोग करें

वैकल्पिक रूप से, दूसरी और तीसरी तालिका में डालने के लिए पहली तालिका पर ट्रिगर बनाएं


आप तीन नौकरियों का निर्माण करने की कोशिश कर सकते हैं और समानांतर में डालने वाली स्क्रिप्ट निष्पादित कर सकते हैं:

DECLARE @jobId BINARY(16)
EXEC msdb.dbo.sp_add_job @job_name=N'Job1', 
        @enabled=1,  
        @description=N'No description available.', 
        @job_id = @jobId OUTPUT

EXEC msdb.dbo.sp_add_jobstep @job_id[email protected]jobId, @step_name=N'Insert into First Table', 
        @step_id=1, 
        @cmdexec_success_code=0, 
        @on_success_action=1, 
        @on_success_step_id=0, 
        @on_fail_action=2, 
        @on_fail_step_id=0, 
        @retry_attempts=0, 
        @retry_interval=0, 
        @os_run_priority=0, @subsystem=N'TSQL', 
        @command=N'--Insert script for first table', 
        @database_name=N'Test', 
        @flags=0

EXEC msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
GO

DECLARE @jobId BINARY(16)
EXEC msdb.dbo.sp_add_job @job_name=N'Job2', 
        @enabled=1,  
        @description=N'No description available.', 
        @job_id = @jobId OUTPUT

EXEC msdb.dbo.sp_add_jobstep @job_id[email protected]jobId, @step_name=N'Insert into second Table', 
        @step_id=1, 
        @cmdexec_success_code=0, 
        @on_success_action=1, 
        @on_success_step_id=0, 
        @on_fail_action=2, 
        @on_fail_step_id=0, 
        @retry_attempts=0, 
        @retry_interval=0, 
        @os_run_priority=0, @subsystem=N'TSQL', 
        @command=N'--Insert script for second table', 
        @database_name=N'Test', 
        @flags=0

EXEC msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
GO

DECLARE @jobId BINARY(16)
EXEC msdb.dbo.sp_add_job @job_name=N'Job3', 
        @enabled=1,  
        @description=N'No description available.', 
        @job_id = @jobId OUTPUT

EXEC msdb.dbo.sp_add_jobstep @job_id[email protected]jobId, @step_name=N'Insert into Third Table', 
        @step_id=1, 
        @cmdexec_success_code=0, 
        @on_success_action=1, 
        @on_success_step_id=0, 
        @on_fail_action=2, 
        @on_fail_step_id=0, 
        @retry_attempts=0, 
        @retry_interval=0, 
        @os_run_priority=0, @subsystem=N'TSQL', 
        @command=N'--Insert script for third table', 
        @database_name=N'Test', 
        @flags=0

EXEC msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
GO

EXEC msdb.dbo.sp_start_job N'Job1' ; --All will execute in parallel
EXEC msdb.dbo.sp_start_job N'Job2' ;
EXEC msdb.dbo.sp_start_job N'Job3' ;

विवरण टी-एसक्यूएल बैच के भीतर तुल्यकालन निष्पादित करते हैं। संग्रहीत कार्यविधि से समकालिक और समानांतर में कई बयानों को निष्पादित करने के लिए, आपको एकाधिक समवर्ती डेटाबेस कनेक्शन का उपयोग करने की आवश्यकता होगी। ध्यान दें कि एसिंक्रोनस निष्पादन के साथ मुश्किल भाग न केवल जब सभी कार्यों को पूरा कर लिया है, बल्कि यह भी निर्धारित किया जाता है कि क्या वे सफल या असफल रहे हैं

विधि 1: SSIS पैकेज

समानांतर में 3 एसक्यूएल स्टेटमेंट निष्पादित करने के लिए एक SSIS पैकेज बनाएँ। एसक्यूएल 2012 और बाद में, एसएसआईएस कैटलॉग संग्रहित प्रक्रियाओं का उपयोग कर पैकेज चलाएं। पूर्व-एसक्यूएल 2012, आपको पैकेज के लिए एसक्यूएल एजेंट की नौकरी बनाने और sp_start_job के साथ लॉन्च करने की आवश्यकता होगी।

आपको एसएसआईएस निष्पादन स्थिति या एसक्यूएल एजेंट काम की स्थिति को पूरा करने, और सफलता / असफलता के परिणाम की जांच करने की आवश्यकता होगी।

विधि 2: पावरहेल और एसक्यूएल एजेंट

एक SQL एजेंट नौकरी निष्पादित करें जो पावरशेल्ड स्क्रिप्ट चलाती है जो पॉवरशेले पृष्ठभूमि नौकरियों (आरंभ-नौकरी कमांड) का उपयोग करते हुए समानांतर क्वेरीज़ को निष्पादित करती है। स्क्रिप्ट किसी निकास कोड, सफलता के लिए शून्य और असफलता के लिए गैर-शून्य लौटा सकता है, ताकि SQL एजेंट निर्धारित कर सके कि यह सफल हो गया है या नहीं। समापन, और सफलता / विफलता परिणाम का निर्धारण करने के लिए SQL एजेंट कार्य स्थिति की जांच करें

विधि 3: एकाधिक एसक्यूएल एजेंट नौकरियां

एक साथ एकाधिक एसक्यूएल एजेंट नौकरियां निष्पादित करें, प्रत्येक में एक टी-एसक्यूएल नौकरी कदम आयात स्क्रिप्ट से युक्त। पूर्णता, और सफलता / विफलता परिणाम का निर्धारण करने के लिए प्रत्येक कार्य की SQL एजेंट कार्य स्थिति की जांच करें

विधि 4: सेवा ब्रोकर समानांतर में आयात स्क्रिप्ट निष्पादित करने के लिए एक पंक्ति सक्रियित proc का उपयोग करें। यदि आप सेवा दलाल से पहले नहीं इस्तेमाल किया है और यह vetted पैटर्न का पालन करना महत्वपूर्ण है, तो यह कटु हो सकता है मैंने आपको आरंभ करने के लिए एक उदाहरण शामिल किया है (pre-SQL 2012 के लिए RAISERROR के साथ थ्रू बदलें)। डेटाबेस में सेवा ब्रोकर को सक्षम होना चाहिए, जो डिफ़ॉल्ट रूप से सक्षम है, लेकिन इसे पुनर्स्थापित या अनुलग्नित करने के बाद बंद कर दिया गया है।

USE YourDatabase;
Go

--create proc that will be automatically executed (activated) when requests are waiting
CREATE PROC dbo.ExecuteTSqlTask
AS
SET NOCOUNT ON;

DECLARE
      @TSqlJobConversationHandle uniqueidentifier = NEWID()
    , @TSqlExecutionRequestMessage xml
    , @TSqlExecutionResultMessage xml
    , @TSqlExecutionResult varchar(10)
    , @TSqlExecutionResultDetails nvarchar(MAX)
    , @TSqlScript nvarchar(MAX)
    , @TSqlTaskName sysname
    , @RowsAffected int
    , @message_type_name sysname;

WHILE 1 = 1
BEGIN

    --get the next task to execute
    WAITFOR (
        RECEIVE TOP (1)
              @TSqlJobConversationHandle = conversation_handle
            , @TSqlExecutionRequestMessage = CAST(message_body AS xml)
            , @message_type_name = message_type_name
        FROM dbo.TSqlExecutionQueue
        ), TIMEOUT 1000;

    IF @@ROWCOUNT = 0
    BEGIN
        --no work to do - exit
        BREAK;
    END;

    IF @message_type_name = N'TSqlExecutionRequest'
    BEGIN

        --get task name and script
        SELECT
              @TSqlTaskName = @TSqlExecutionRequestMessage.value('(/TSqlTaskName)[1]', 'sysname')
            , @TSqlScript = @TSqlExecutionRequestMessage.value('(/TSqlScript)[1]', 'nvarchar(MAX)');

        --execute script
        BEGIN TRY
            EXEC sp_executesql @TSqlScript;
            SET @RowsAffected = @@ROWCOUNT;
            SET @TSqlExecutionResult = 'Completed';
            SET @TSqlExecutionResultDetails = CAST(@RowsAffected as varchar(10)) + ' rows affected';
        END TRY
        BEGIN CATCH
            SET @TSqlExecutionResult = 'Erred';
            SET @TSqlExecutionResultDetails = 
                  'Msg ' + CAST(ERROR_NUMBER() AS varchar(10))
                + ', Level ' + CAST(ERROR_SEVERITY() AS varchar(2))
                + ', State ' + CAST(ERROR_STATE() AS varchar(10))
                + ', Line ' + CAST(ERROR_LINE() AS varchar(10))
                + ': ' + ERROR_MESSAGE();
        END CATCH;

        --send execution result back to initiator
        SET @TSqlExecutionResultMessage = '<TSqlTaskName /><TSqlExecutionResult /><TSqlExecutionResultDetails />';
        SET @TSqlExecutionResultMessage.modify('insert text {sql:variable("@TSqlTaskName")} into (/TSqlTaskName)[1] ');
        SET @TSqlExecutionResultMessage.modify('insert text {sql:variable("@TSqlExecutionResult")} into (/TSqlExecutionResult)[1] ');
        SET @TSqlExecutionResultMessage.modify('insert text {sql:variable("@TSqlExecutionResultDetails")} into (/TSqlExecutionResultDetails)[1] ');
        SEND ON CONVERSATION @TSqlJobConversationHandle
            MESSAGE TYPE TSqlExecutionResult
            (@TSqlExecutionResultMessage);

    END
    ELSE
    BEGIN
        IF @message_type_name = N'TSqlJobComplete'
        BEGIN
            --service has ended conversation so we're not going to get any more execution requests
            END CONVERSATION @TSqlJobConversationHandle;
        END
        ELSE
        BEGIN
            END CONVERSATION @TSqlJobConversationHandle WITH ERROR = 1 DESCRIPTION = 'Unexpected message type received by ExecuteTSqlTask';
            RAISERROR('Unexpected message type received (%s) by ExecuteTSqlTask', 16, 1, @message_type_name);
        END;
    END;
END;
GO

CREATE QUEUE dbo.TSqlResultQueue;
CREATE QUEUE dbo.TSqlExecutionQueue
    WITH STATUS=ON,
    ACTIVATION (
          STATUS = ON
        , PROCEDURE_NAME = dbo.ExecuteTSqlTask
        , MAX_QUEUE_READERS = 3 --max number of concurrent activated proc instances 
        , EXECUTE AS OWNER
        );
CREATE MESSAGE TYPE TSqlExecutionRequest VALIDATION = WELL_FORMED_XML;
CREATE MESSAGE TYPE TSqlExecutionResult VALIDATION = WELL_FORMED_XML;
CREATE MESSAGE TYPE TSqlJobComplete VALIDATION = WELL_FORMED_XML;
CREATE CONTRACT TSqlExecutionContract (
      TSqlExecutionRequest SENT BY INITIATOR
    , TSqlJobComplete SENT BY INITIATOR
    , TSqlExecutionResult SENT BY TARGET
    );
CREATE SERVICE TSqlJobService ON QUEUE dbo.TSqlResultQueue ([TSqlExecutionContract]);
CREATE SERVICE TSqlExecutorService ON QUEUE dbo.TSqlExecutionQueue ([TSqlExecutionContract]);
GO

CREATE PROC dbo.ExecuteParallelImportScripts
AS
SET NOCOUNT ON;

DECLARE
      @TSqlJobConversationHandle uniqueidentifier
    , @TSqlExecutionRequestMessage xml
    , @TSqlExecutionResultMessage xml
    , @TSqlExecutionResult varchar(10)
    , @TSqlExecutionResultDetails nvarchar(MAX)
    , @TSqlTaskName sysname
    , @CompletedCount int = 0
    , @ErredCount int = 0
    , @message_type_name sysname;

DECLARE @TsqlTask TABLE(
      TSqlTaskName sysname NOT NULL PRIMARY KEY 
    , TSqlScript nvarchar(MAX) NOT NULL
    );

BEGIN TRY

    --insert a row for each import task
    INSERT INTO @TsqlTask(TSqlTaskName, TSqlScript) 
        VALUES(N'ImportScript1', N'INSERT INTO dbo.Table1 SELECT * FROM dbo.Table1Staging;');
    INSERT INTO @TsqlTask(TSqlTaskName, TSqlScript) 
        VALUES(N'ImportScript2', N'INSERT INTO dbo.Table2 SELECT * FROM dbo.Table2Staging;');
    INSERT INTO @TsqlTask(TSqlTaskName, TSqlScript) 
        VALUES(N'ImportScript3', N'INSERT INTO dbo.Table3 SELECT * FROM dbo.Table3Staging;');

    --start a conversation for this import process
    BEGIN DIALOG CONVERSATION @TsqlJobConversationHandle
        FROM SERVICE TSqlJobService
        TO SERVICE 'TSqlExecutorService', 'CURRENT DATABASE'
        ON CONTRACT TSqlExecutionContract
        WITH ENCRYPTION = OFF;

    --send import tasks to executor service for parallel execution
    DECLARE JobTasks CURSOR LOCAL FAST_FORWARD FOR
        SELECT (SELECT TSqlTaskName, TSqlScript
            FROM @TsqlTask AS task 
            WHERE task.TSqlTaskName = job.TSqlTaskName
            FOR XML PATH(''), TYPE) AS TSqlExecutionRequest
        FROM @TsqlTask AS job;
    OPEN JobTasks;
    WHILE 1 = 1
    BEGIN
        FETCH NEXT FROM JobTasks INTO @TSqlExecutionRequestMessage;
        IF @@FETCH_STATUS = -1 BREAK;
        SEND ON CONVERSATION @TSqlJobConversationHandle
            MESSAGE TYPE TSqlExecutionRequest
            (@TSqlExecutionRequestMessage);
    END;
    CLOSE JobTasks;
    DEALLOCATE JobTasks;

    --get each parallel task execution result until all are complete
    WHILE 1 = 1
    BEGIN

        --get next task result
        WAITFOR (
            RECEIVE TOP (1)
                  @TSqlExecutionResultMessage = CAST(message_body AS xml)
                , @message_type_name = message_type_name
            FROM dbo.TSqlResultQueue
            WHERE conversation_handle = @TSqlJobConversationHandle
            ), TIMEOUT 1000;

        IF @@ROWCOUNT <> 0
        BEGIN

            IF @message_type_name = N'TSqlExecutionResult'
            BEGIN

                --get result of import script execution
                SELECT
                      @TSqlTaskName = @TSqlExecutionResultMessage.value('(/TSqlTaskName)[1]', 'sysname')
                    , @TSqlExecutionResult = @TSqlExecutionResultMessage.value('(/TSqlExecutionResult)[1]', 'varchar(10)')
                    , @TSqlExecutionResultDetails = COALESCE(@TSqlExecutionResultMessage.value('(/TSqlExecutionResultDetails)[1]', 'nvarchar(MAX)'), N'');
                RAISERROR('Import task %s %s: %s', 0, 0, @TSqlTaskName, @TSqlExecutionResult, @TSqlExecutionResultDetails) WITH NOWAIT;
                IF @TSqlExecutionResult = 'Completed'
                BEGIN
                    SET @CompletedCount += 1;
                END
                ELSE
                BEGIN
                    SET @ErredCount += 1;
                END;

                --remove task from tracking table after completion
                DELETE FROM @TSqlTask
                WHERE TSqlTaskName = @TSqlTaskName;

                IF NOT EXISTS(SELECT 1 FROM @TsqlTask)
                BEGIN
                    --all tasks are done - send TSqlJobComplete message to instruct executor service to end conversation
                    SEND ON CONVERSATION @TSqlJobConversationHandle
                        MESSAGE TYPE TSqlJobComplete;
                END
            END
            ELSE
            BEGIN
                IF @message_type_name = N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog'
                BEGIN
                    --executor service has ended conversation so we're done
                    END CONVERSATION @TSqlJobConversationHandle;
                    BREAK;
                END
                ELSE
                BEGIN
                    END CONVERSATION @TSqlJobConversationHandle WITH ERROR = 1 DESCRIPTION = 'Unexpected message type received by ExecuteParallelInserts';
                    RAISERROR('Unexpected message type received (%s) by ExecuteParallelInserts', 16, 1, @message_type_name);
                END;
            END
        END;
    END;
    RAISERROR('Import processing completed. CompletedCount=%d, ErredCount=%d.', 0, 0, @CompletedCount, @ErredCount);
END TRY
BEGIN CATCH
    THROW;
END CATCH;
GO

--execute import scripts in parallel
EXEC dbo.ExecuteParallelImportScripts;
GO

क्या सूची पुनर्प्राप्त करने का कोई तरीका है लेकिन इस कॉलम के बिना?

प्रक्षेपण के बिना नहीं, जिसे आप टालना चाहते हैं। यदि कॉलम मैप किया गया है तो यह आपकी इकाई का प्राकृतिक हिस्सा है। इस कॉलम के बिना इकाई पूर्ण नहीं है - यह अलग डेटा सेट = प्रक्षेपण है।

मैं यहां अज्ञात प्रकार का उपयोग कर रहा हूं क्योंकि अन्यथा आपको एक असमर्थित अपवाद प्राप्त होगा: इकाई या जटिल प्रकार 'ProjectName.File' को LINQ से Entities क्वेरी में नहीं बनाया जा सकता है।

अपवाद के रूप में आप कहते हैं कि आप मैप किए गए इकाई को प्रोजेक्ट नहीं कर सकते हैं। मैंने उपर्युक्त कारण का उल्लेख किया - प्रक्षेपण अलग-अलग डेटा सेट बनाते हैं और ईएफ को "आंशिक संस्थाएं" पसंद नहीं है।

त्रुटि 16 त्रुटि 3023: लाइन 2717 से शुरू होने वाले टुकड़ों को मैप करने में समस्या: कॉलम फ़ाइलें। तालिका में डेटा फ़ाइलों को मैप किया जाना चाहिए: इसका कोई डिफ़ॉल्ट मान नहीं है और यह शून्य नहीं है।

डिजाइनर से संपत्ति को हटाने के लिए पर्याप्त नहीं है। आपको ईडीएमएक्स को एक्सएमएल के रूप में खोलना होगा और एसएसडीएल से कॉलम भी हटा देना होगा जिससे आपका मॉडल बहुत नाजुक हो जाएगा (डेटाबेस से प्रत्येक अपडेट आपके कॉलम को वापस रखेगा)। यदि आप कॉलम को मैप करना नहीं चाहते हैं तो आपको कॉलम के बिना डेटाबेस दृश्य का उपयोग करना चाहिए और तालिका के बजाय दृश्य को मानचित्र बनाना चाहिए लेकिन आप डेटा सम्मिलित नहीं कर पाएंगे।

आपकी सभी समस्याओं के समाधान के रूप में टेबल विभाजन का उपयोग करें और समस्याग्रस्त बाइनरी कॉलम को किसी अन्य इकाई से अलग करें, जिसमें आपकी मुख्य File इकाई के 1: 1 संबंध हैं।





sql sql-server sql-server-2008 tsql sql-server-2012