سؤال

لديّ جدولان كبيران (188 مترًا و144 مترًا) أحتاج إلى ملؤهما من طرق العرض، لكن كل عرض يحتوي على بضع مئات الملايين من الصفوف (يجمع البيانات ذات النماذج الزائفة معًا في نموذج مسطح).المفاتيح الموجودة في كل جدول تزيد عن 50 بايت مركب من الأعمدة.إذا كانت البيانات موجودة في الجداول، فيمكنني دائمًا التفكير في استخدام sp_rename لإنشاء الجدول الجديد الآخر، ولكن هذا ليس خيارًا حقًا.

إذا قمت بإجراء عملية INSERT واحدة، فإن العملية تستخدم قدرًا كبيرًا من مساحة سجل المعاملات، مما يؤدي إلى حفظها بشكل نموذجي ويؤدي إلى مجموعة من المتاعب مع مسؤولي قواعد البيانات.(ونعم، ربما تكون هذه هي الوظيفة التي يجب على مسؤولي قواعد البيانات التعامل معها/التصميم/المهندس المعماري)

يمكنني استخدام SSIS ودفق البيانات إلى الجدول الوجهة مع الالتزامات المجمعة (ولكن هذا يتطلب نقل البيانات عبر الشبكة، حيث لا يُسمح لنا بتشغيل حزم SSIS على الخادم).

هل هناك أي أشياء بخلاف تقسيم العملية إلى عمليات INSERT متعددة باستخدام نوع من المفاتيح لتوزيع الصفوف على دفعات مختلفة وإجراء حلقة؟

هل كانت مفيدة؟

المحلول

هل يمكن تقسيم بياناتك وادخال البيانات الخاصة بك في حلقة المؤشر. ومن شأن ذلك أن يكون تقريبا نفس جهاز مباحث أمن الدولة batchinserting. ولكن يعمل على الخادم الخاص بك.

create cursor ....
select YEAR(DateCol), MONTH(DateCol) from whatever

while ....
    insert into yourtable(...)
    select * from whatever 
    where YEAR(DateCol) = year and MONTH(DateCol) = month
end

نصائح أخرى

هل لديها وجهة نظر أي نوع من فريد المفتاح معرف / المرشح؟ إذا كان الأمر كذلك، هل يمكن تحديد تلك الصفوف في جدول العمل باستخدام:

SELECT key_columns INTO dbo.temp FROM dbo.HugeView;

و(إذا كان من المنطقي، وربما وضع هذا الجدول في قاعدة بيانات مختلفة، وربما مع طراز الاسترداد بسيطة، لمنع النشاط سجل من التدخل في قاعدة البيانات الأساسية الخاصة بك. وينبغي لهذه توليد أقل بكثير تسجيل على أي حال، ويمكنك تحرير ل الفضاء في قاعدة بيانات أخرى قبل استئناف، في حالة والمشكلة هي أن لديك مساحة القرص غير كاف في كل مكان.)

وبعد ذلك يمكنك أن تفعل شيئا من هذا القبيل، وإدراج 10،000 الصفوف في وقت واحد، والنسخ الاحتياطي سجل في بين:

SET NOCOUNT ON;

DECLARE
    @batchsize INT,
    @ctr INT,
    @rc INT;

SELECT
    @batchsize = 10000,
    @ctr = 0;

WHILE 1 = 1
BEGIN
    WITH x AS
    (
        SELECT key_column, rn = ROW_NUMBER() OVER (ORDER BY key_column)
        FROM dbo.temp
    )
    INSERT dbo.PrimaryTable(a, b, c, etc.)
        SELECT v.a, v.b, v.c, etc.
        FROM x
        INNER JOIN dbo.HugeView AS v
        ON v.key_column = x.key_column
        WHERE x.rn > @batchsize * @ctr
        AND x.rn <= @batchsize * (@ctr + 1);

    IF @@ROWCOUNT = 0
        BREAK;

    BACKUP LOG PrimaryDB TO DISK = 'C:\db.bak' WITH INIT;

    SET @ctr = @ctr + 1;
END

وهذا كل من على قمة رأسي، لذلك لا قطع / لصق / تشغيل، ولكن أعتقد أن الفكرة العامة هي هناك.

لاحظ أنه إذا كنت تأخذ قاعدة بيانات عادية وتسجيل عمليات النسخ الاحتياطي وربما كنت تريد أن تأخذ كامل لبدء سلسلة السجل الخاص بك مرة أخرى.

وأنا أعلم أن هذا هو موضوع قديم، ولكن أنا قدمت صيغة عامة من حل المؤشر آرثر:

--Split a batch up into chunks using a cursor.
--This method can be used for most any large table with some modifications
--It could also be refined further with an @Day variable (for example)

DECLARE @Year INT
DECLARE @Month INT

DECLARE BatchingCursor CURSOR FOR
SELECT DISTINCT YEAR(<SomeDateField>),MONTH(<SomeDateField>)
FROM <Sometable>;


OPEN BatchingCursor;
FETCH NEXT FROM BatchingCursor INTO @Year, @Month;
WHILE @@FETCH_STATUS = 0
BEGIN

--All logic goes in here
--Any select statements from <Sometable> need to be suffixed with:
--WHERE Year(<SomeDateField>)=@Year AND Month(<SomeDateField>)=@Month   


  FETCH NEXT FROM BatchingCursor INTO @Year, @Month;
END;
CLOSE BatchingCursor;
DEALLOCATE BatchingCursor;
GO

وتحل هذه المشكلة على كميات من جداول كبيرة لدينا.

وليس هناك غبار الجنية، وانت تعرف ذلك.

ودون معرفة تفاصيل حول المخطط الفعلي نقله، فإن حل عام يكون بالضبط كما كنت أصف ذلك: معالجة الفجوة في إدراج متعددة وتتبع مفتاح (ق). هذا هو نوع من شبه رمز T-SQL:

create table currentKeys (table sysname not null primary key, key sql_variant not null);
go

declare @keysInserted table (key sql_variant);
declare @key sql_variant;
begin transaction
do while (1=1)
begin
    select @key = key from currentKeys where table = '<target>';
    insert into <target> (...)
    output inserted.key into @keysInserted (key)
    select top (<batchsize>) ... from <source>
    where key > @key
    order by key;

    if (0 = @@rowcount)
       break; 

    update currentKeys 
    set key = (select max(key) from @keysInserted)
    where table = '<target>';
    commit;
    delete from @keysInserted;
    set @key = null;
    begin transaction;
end
commit

وسيكون الحصول على أكثر تعقيدا إذا كنت ترغب في السماح للدفعات موازية وتقسيم المفاتيح.

يمكنك استخدام أمر BCP لتحميل البيانات واستخدام معلمة Batch Size

http://msdn.microsoft.com/en-us/library/ms162802.aspx

عملية من خطوتين

  • بيانات BCP OUT من طرق العرض إلى ملفات نصية
  • بيانات BCP IN من الملفات النصية إلى جداول ذات معلمة حجم الدُفعة

وهذا يبدو وكأنه وظيفة لحسن رأ ' BCP .

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top