ইনডেক্সড টেবিলগুলিতে whenোকানোর সময় কেন আমি ন্যূনতম লগিং পাচ্ছি না


14

আমি বিভিন্ন পরিস্থিতিতে ন্যূনতম লগিং সন্নিবেশ পরীক্ষা করছি এবং আমি যা পড়েছি তা থেকে টব্লক এবং এসকিউএল সার্ভার 2016+ ব্যবহার করে একটি ক্লাস্টারযুক্ত সূচী দিয়ে একটি স্তূপের মধ্যে সন্নিবেশ নির্বাচন করুন যা আমার ক্ষেত্রে এটি করার সময় আমি পেয়ে যাচ্ছি সম্পূর্ণ লগিং। আমার ডাটাবেসটি সহজ পুনরুদ্ধারের মডেলটিতে রয়েছে এবং আমি সফলভাবে কোনও সূচি এবং ট্যাব্লক ছাড়াই একটি গাদাতে ন্যূনতমভাবে লগ ইনসার্টগুলি পাই get

আমি পরীক্ষার জন্য স্ট্যাক ওভারফ্লো ডাটাবেসের একটি পুরানো ব্যাকআপ ব্যবহার করছি এবং নিম্নলিখিত স্কিমা সহ পোস্ট টেবিলের একটি প্রতিলিপি তৈরি করেছি ...

CREATE TABLE [dbo].[PostsDestination](
    [Id] [int] NOT NULL,
    [AcceptedAnswerId] [int] NULL,
    [AnswerCount] [int] NULL,
    [Body] [nvarchar](max) NOT NULL,
    [ClosedDate] [datetime] NULL,
    [CommentCount] [int] NULL,
    [CommunityOwnedDate] [datetime] NULL,
    [CreationDate] [datetime] NOT NULL,
    [FavoriteCount] [int] NULL,
    [LastActivityDate] [datetime] NOT NULL,
    [LastEditDate] [datetime] NULL,
    [LastEditorDisplayName] [nvarchar](40) NULL,
    [LastEditorUserId] [int] NULL,
    [OwnerUserId] [int] NULL,
    [ParentId] [int] NULL,
    [PostTypeId] [int] NOT NULL,
    [Score] [int] NOT NULL,
    [Tags] [nvarchar](150) NULL,
    [Title] [nvarchar](250) NULL,
    [ViewCount] [int] NOT NULL
)
CREATE NONCLUSTERED INDEX ndx_PostsDestination_Id ON PostsDestination(Id)

আমি তখন এই টেবিলের মধ্যে পোস্ট টেবিলটি অনুলিপি করার চেষ্টা করি ...

INSERT INTO PostsDestination WITH(TABLOCK)
SELECT * FROM Posts ORDER BY Id 

Fn_dblog এবং লগ ফাইলের ব্যবহার দেখে আমি দেখতে পাচ্ছি যে আমি এ থেকে ন্যূনতম লগিং পাচ্ছি না। আমি যে সংস্করণগুলি পড়েছি তা ২০১ read এর আগে পড়েছিলাম ট্রেড পতাকা 6১০ এর জন্য ন্যূনতমভাবে সূচিযুক্ত টেবিলগুলিতে লগ করার জন্য, আমি এটিও সেট করার চেষ্টা করেছি তবে এখনও কোনও আনন্দ নেই।

আমি অনুমান করছি আমি এখানে কিছু মিস করছি?

সম্পাদনা - আরও তথ্য

আরও তথ্য যুক্ত করতে আমি নিম্নলিখিত পদ্ধতিটি ব্যবহার করছি যা আমি ন্যূনতম লগিং সনাক্ত করার চেষ্টা করার জন্য লিখেছি, সম্ভবত আমার এখানে কিছু ভুল হয়েছে ...

/*
    Example Usage...

    EXEC sp_GetLogUseStats
   @Sql = '
      INSERT INTO PostsDestination
      SELECT TOP 500000 * FROM Posts ORDER BY Id ',
   @Schema = 'dbo',
   @Table = 'PostsDestination',
   @ClearData = 1

*/

CREATE PROCEDURE [dbo].[sp_GetLogUseStats]
(   
   @Sql NVARCHAR(400),
   @Schema NVARCHAR(20),
   @Table NVARCHAR(200),
   @ClearData BIT = 0
)
AS

IF @ClearData = 1
   BEGIN
   TRUNCATE TABLE PostsDestination
   END

/*Checkpoint to clear log (Assuming Simple/Bulk Recovery Model*/
CHECKPOINT  

/*Snapshot of logsize before query*/
CREATE TABLE #BeforeLogUsed(
   [Db] NVARCHAR(100),
   LogSize NVARCHAR(30),
   Used NVARCHAR(50),
   Status INT
)
INSERT INTO #BeforeLogUsed
EXEC('DBCC SQLPERF(logspace)')

/*Run Query*/
EXECUTE sp_executesql @SQL

/*Snapshot of logsize after query*/
CREATE TABLE #AfterLLogUsed(    
   [Db] NVARCHAR(100),
   LogSize NVARCHAR(30),
   Used NVARCHAR(50),
   Status INT
)
INSERT INTO #AfterLLogUsed
EXEC('DBCC SQLPERF(logspace)')

/*Return before and after log size*/
SELECT 
   CAST(#AfterLLogUsed.Used AS DECIMAL(12,4)) - CAST(#BeforeLogUsed.Used AS DECIMAL(12,4)) AS LogSpaceUsersByInsert
FROM 
   #BeforeLogUsed 
   LEFT JOIN #AfterLLogUsed ON #AfterLLogUsed.Db = #BeforeLogUsed.Db
WHERE 
   #BeforeLogUsed.Db = DB_NAME()

/*Get list of affected indexes from insert query*/
SELECT 
   @Schema + '.' + so.name + '.' +  si.name AS IndexName
INTO 
   #IndexNames
FROM 
   sys.indexes si 
   JOIN sys.objects so ON si.[object_id] = so.[object_id]
WHERE 
   si.name IS NOT NULL
   AND so.name = @Table
/*Insert Record For Heap*/
INSERT INTO #IndexNames VALUES(@Schema + '.' + @Table)

/*Get log recrod sizes for heap and/or any indexes*/
SELECT 
   AllocUnitName,
   [operation], 
   AVG([log record length]) AvgLogLength,
   SUM([log record length]) TotalLogLength,
   COUNT(*) Count
INTO #LogBreakdown
FROM 
   fn_dblog(null, null) fn
   INNER JOIN #IndexNames ON #IndexNames.IndexName = allocunitname
GROUP BY 
   [Operation], AllocUnitName
ORDER BY AllocUnitName, operation

SELECT * FROM #LogBreakdown
SELECT AllocUnitName, SUM(TotalLogLength)  TotalLogRecordLength 
FROM #LogBreakdown
GROUP BY AllocUnitName

নিম্নলিখিত কোড ব্যবহার করে কোনও সূচি এবং ট্যাব্লকবিহীন একটি গাদাতে প্রবেশ করা হচ্ছে ...

EXEC sp_GetLogUseStats
   @Sql = '
      INSERT INTO PostsDestination
      SELECT * FROM Posts ORDER BY Id ',
   @Schema = 'dbo',
   @Table = 'PostsDestination',
   @ClearData = 1

আমি এই ফলাফল পেতে

এখানে চিত্র বর্ণনা লিখুন

0.0024mb লগ ফাইলের বৃদ্ধি, খুব ছোট লগ রেকর্ড আকার এবং তাদের মধ্যে খুব কম আমি খুশি যে এটি ন্যূনতম লগিং ব্যবহার করছে।

আমি যদি তখন আইডি তে একটি ক্লাস্টারযুক্ত সূচক তৈরি করি ...

CREATE INDEX ndx_PostsDestination_Id ON PostsDestination(Id)

তারপরে আবার আমার একই সন্নিবেশ চালান ...

এখানে চিত্র বর্ণনা লিখুন

আমি নন-ক্লাস্টারড ইনডেক্সে ন্যূনতম লগিং পাচ্ছি না তবে আমি এটি হিটে হারিয়েছি। আরও কিছু পরীক্ষা করার পরে মনে হয় যদি আমি আইডি ক্লাস্টার তৈরি করি তবে এটি ন্যূনতমভাবে লগ করে তবে যা আমি ২০১০+ পড়েছি তা থেকে নকল ক্লাস্টারযুক্ত সূচকের সাথে নূন্যতম লগ করা উচিত যখন ট্যাবলক ব্যবহার করা হয়।

শেষ সম্পাদনা :

আমি এসকিউএল সার্ভার ইউজারওয়য়েসে মাইক্রোসফ্টের কাছে আচরণটির কথা জানিয়েছি এবং আমি কোনও প্রতিক্রিয়া পেলে আপডেট করব। আমি https://gavindraper.com/2018/05/29/SQL-Server- মিনিমাল- লগিং- ইনসার্টস / এ কাজ করতে পারি না এমন ন্যূনতম লগ দৃশ্যের পুরো বিবরণটিও লিখে রেখেছি


উত্তর:


12

আমি স্ট্যাক ওভারফ্লো 2010 ডাটাবেস ব্যবহার করে এসকিউএল সার্ভারে আপনার ফলাফলগুলি পুনরুত্পাদন করতে পারি, তবে (উপসংহারে) আপনার সিদ্ধান্তে নেই।

সংক্ষিপ্ত লগিং করার গাদা উপলব্ধ ব্যবহার করছে INSERT...SELECTসঙ্গে TABLOCKএকটি nonclustered সূচক, যা দিয়ে এক গাদা থেকে অপ্রত্যাশিত । আমার ধারণা হ'ল (বি-ট্রি) একই সাথে (হিপ) INSERT...SELECTব্যবহার করে বাল্ক বোঝা সমর্থন করতে পারে না । শুধুমাত্র মাইক্রোসফ্ট নিশ্চিত করতে সক্ষম হবে যে এটি কোনও বাগ বা ডিজাইনের মাধ্যমে হয়।RowsetBulkFastLoadContext

Nonclustered সূচক গাদা উপর ন্যূনতমরূপে লগ করা হয় (অভিমানী TF610 চালু থাকে, তখন বা SQL সার্ভার 2016+ ব্যবহার করা হয়, সক্রিয় FastLoadContext) নিম্নলিখিত আদেশ সহকারে সঙ্গে

  • সদ্য সঞ্চিত পৃষ্ঠাগুলিতে সন্নিবেশ করা সারিগুলি ন্যূনতমভাবে লগ হয়।
  • প্রথম সূচী পৃষ্ঠায় যুক্ত সারিগুলি ন্যূনতমভাবে লগ করা হয় না, যদি ক্রিয়াকলাপের শুরুতে সূচকটি খালি থাকে।

LOP_INSERT_ROWSঅবিচ্ছিন্ন সূচকের জন্য প্রদর্শিত 497 টি সূচি সূচকের প্রথম পৃষ্ঠার সাথে মিলে। সূচকটি আগে থেকেই খালি ছিল, এই সারিগুলি সম্পূর্ণরূপে লগড। বাকি সারিগুলি সমস্ত ন্যূনতমভাবে লগড । যদি ডকুমেন্টেড ট্রেস ফ্ল্যাগ 692 অক্ষম করতে সক্ষম হয় (2016+) FastLoadContext, অবিচ্ছিন্ন সমস্ত সূচক সারি ন্যূনতম লগড।


আমি দেখতে পেলাম যে কোনও ফাইল থেকে ব্যবহার করে বাল্ক একই টেবিলটি (সূচী সহ) লোড করার সময় হিপ এবং ননক্র্লাস্টারড উভয় সূচকেই ন্যূনতম লগিং প্রয়োগ করা হয় :BULK INSERT

BULK INSERT dbo.PostsDestination
FROM 'D:\SQL Server\Posts.bcp'
WITH (TABLOCK, DATAFILETYPE = 'native');

আমি সম্পূর্ণতার জন্য এটি নোট। বাল্ক লোডিং ব্যবহার INSERT...SELECTকরে বিভিন্ন কোড পাথ ব্যবহার করা হয় , সুতরাং আচরণের যে পার্থক্য রয়েছে তা সম্পূর্ণ অপ্রত্যাশিত নয়।


জন্য পূর্ণ বিবরণ ব্যবহার ন্যূনতম লগিং সম্পর্কে RowsetBulkএবং FastLoadContextসঙ্গে INSERT...SELECTSQLPerformance.com উপর আমার তিন অংশ সিরিজ দেখুন:

  1. অন্তর্ভুক্ত ন্যূনতম লগিং ... হিপ টেবিলগুলিতে নির্বাচন করুন
  2. অন্তর্ভুক্ত ন্যূনতম লগিং ... খালি ক্লাস্টার টেবিলগুলিতে নির্বাচন করুন
  3. অন্তর্ভুক্ত ন্যূনতম লগিং ... নির্বাচন করুন এবং দ্রুত লোড প্রসঙ্গে

আপনার ব্লগ পোস্ট থেকে অন্যান্য পরিস্থিতিতে

মন্তব্যগুলি বন্ধ রয়েছে তাই আমি এখানে সংক্ষেপে এগুলিকে সম্বোধন করব।

ট্রেস 610 বা 2016+ সহ খালি ক্লাস্টারড ইনডেক্স

এটি FastLoadContextবিনা ব্যবহারে লগইন করা হয় TABLOCK। শুধুমাত্র সম্পূর্ণরূপে লগইন করা সারিগুলি প্রথম পৃষ্ঠায় .োকানো হয়েছে কারণ লেনদেনের শুরুতে ক্লাস্টারড সূচকটি খালি ছিল।

ডেটা এবং ট্রেস 610 বা 2016+ সহ ক্লাস্টার্ড সূচক

এটি ব্যবহার করে ন্যূনতমভাবে লগইন করা হয় FastLoadContext। বিদ্যমান পৃষ্ঠায় যোগ করা সারিগুলি সম্পূর্ণরূপে লগড রয়েছে, বাকী অংশগুলি ন্যূনতম লগড।

ননক্র্লাস্টারড ইনডেক্স এবং ট্যাবলক বা ট্রেস 610 / এসকিউএল 2016+ সহ ক্লাস্টারড ইনডেক্স

এটি FastLoadContextন্যনক্লাস্টারড ইনডেক্স যতক্ষণ না পৃথক অপারেটর দ্বারা বজায় রাখা হয় DMLRequestSortসত্য হিসাবে সেট করা থাকে এবং আমার পোস্টে বর্ণিত অন্যান্য শর্তগুলি পূরণ হয় ততক্ষণ ব্যবহার করে এটি ন্যূনতমভাবে লগ করা যায় ।


2

নীচের নথিটি পুরানো তবে এখনও একটি দুর্দান্ত পঠিত।

এসকিউএল ২০১ 2016-তে ট্রেস পতাকা 610 এবং ALLOW_PAGE_LOCKS ডিফল্টরূপে চালু রয়েছে তবে কেউ এগুলি অক্ষম করে থাকতে পারে।

ডেটা লোড পারফরম্যান্স গাইড

(3) অপ্টিমাইজারের দ্বারা নির্বাচিত পরিকল্পনার উপর নির্ভর করে, টেবিলের অবিচ্ছিন্ন সূচকটি পুরোপুরি বা ন্যূনতমভাবে লগড হতে পারে।

নির্বাচন বাছাই সমস্যা হতে পারে কারণ আপনি একটি শীর্ষ এবং অর্ডার পেয়েছেন। আপনি সূচকে আলাদা ক্রমে টেবিলটিতে ডেটা tingোকাচ্ছেন, যাতে এসকিউএল ব্যাকগ্রাউন্ডে অনেকগুলি বাছাই করতে পারে।

আপডেট 2

আপনি সম্ভবত ন্যূনতম লগিং পাচ্ছেন। ট্রেসফ্লেগ 610 চালু হওয়ার সাথে, লগটি অন্যরকম আচরণ করে, এসকিউএল লগের মধ্যে রোল-ব্যাক সম্পাদন করার জন্য পর্যাপ্ত স্থান সংরক্ষণ করবে যদি কিছু ভুল হয়ে যায় তবে লগটি বাস্তবে ব্যবহার করবে না।

এটি সম্ভবত সংরক্ষিত (অব্যবহৃত) স্থান গণনা করা হচ্ছে

EXEC('DBCC SQLPERF(logspace)')

এই কোডটি ব্যবহৃত থেকে সংরক্ষিত

SELECT
    database_transaction_log_bytes_used
    ,database_transaction_log_bytes_reserved
    ,*
FROM sys.dm_tran_database_transactions 
WHERE database_id = DB_ID()

আমি মনে করি ন্যূনতম লগিং (মাইক্রোসফ্ট সম্পর্কিত হিসাবে) আসলে লগটিতে কমপক্ষে আইওয়ের সঞ্চালন সম্পর্কে, এবং লগের কতটুকু সংরক্ষিত তা নয়।

এই লিঙ্কটি একবার দেখুন ।

আপডেট 1

ট্যাব্লকের পরিবর্তে ট্যাবলকএক্স ব্যবহার করার চেষ্টা করুন। ট্যাবলকের সাহায্যে আপনার এখনও একটি ভাগ করা লক রয়েছে, যাতে এসকিউএল অন্য কোনও প্রক্রিয়া শুরু হওয়ার পরে লগইন করতে পারে।

ট্যাব্লকটি হোল্ডলকের সাথে একযোগে ব্যবহার করার প্রয়োজন হতে পারে। এটি আপনার লেনদেন শেষ না হওয়া অবধি ট্যাবলককে প্রয়োগ করে।

উত্স টেবিল [পোস্টস] এ একটি লকও রাখুন, লগইন হতে পারে কারণ আপনার লেনদেনের সময় সোর্স টেবিলটি পরিবর্তিত হতে পারে। উত্সটি যখন কোনও এসকিউএল টেবিল ছিল না তখন পল হোয়াইট ন্যূনতম লগিং অর্জন করেছিলেন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.