দরিদ্র কার্ডিনালিটির অনুমান ন্যূনতম লগিং থেকে INSERT কে অযোগ্য ঘোষণা করে?


11

দ্বিতীয় INSERTবিবৃতিটি প্রথমটির চেয়ে 5x ডলার কম কেন ?

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


প্রশ্ন # 1: INSERT ব্যবহার করে 5 এমএম সারি সন্নিবেশ করা হচ্ছে ... (ট্যাবলক) সহ

নিম্নলিখিত কোয়েরিটি বিবেচনা করুন, যা 5 এমএম সারিগুলিকে একটি গাদা হিসাবে সন্নিবেশ করায়। এই ক্যোয়ারী বাস্তবায়িত হয় 1 secondএবং 64MBলেনদেন লগ ডেটা দ্বারা রিপোর্ট হিসাবে উত্পন্ন sys.dm_tran_database_transactions

CREATE TABLE dbo.minimalLoggingTest (n INT NOT NULL)
GO
INSERT INTO dbo.minimalLoggingTest WITH (TABLOCK) (n)
SELECT n
-- Any table/view/sub-query that correctly estimates that it will generate 5MM rows
FROM dbo.fiveMillionNumbers
-- Provides greater consistency on my laptop, where other processes are running
OPTION (MAXDOP 1)
GO


ক্যোয়ারী # 2: একই ডেটা সন্নিবেশ করা হচ্ছে, তবে এসকিউএল সারিগুলির # টিকে হ্রাস করে

এখন এই খুব অনুরূপ ক্যোয়ারী বিবেচনা করুন, যা ঠিক একই ডেটাতে কাজ করে তবে একটি টেবিল থেকে আঁকতে দেখা যায় (বা SELECTআমার সত্যিকারের উত্পাদনের ক্ষেত্রে অনেকগুলি সমন্বিত জটিল বিবৃতি) যেখানে কার্ডিনালিটির অনুমান খুব কম। এই ক্যোয়ারী কার্যকর করে 5.5 secondsএবং 461MBলেনদেনের লগ ডেটা তৈরি করে।

CREATE TABLE dbo.minimalLoggingTest (n INT NOT NULL)
GO
INSERT INTO dbo.minimalLoggingTest WITH (TABLOCK) (n)
SELECT n
-- Any table/view/sub-query that produces 5MM rows but SQL estimates just 1000 rows
FROM dbo.fiveMillionNumbersBadEstimate
-- Provides greater consistency on my laptop, where other processes are running
OPTION (MAXDOP 1)
GO


সম্পূর্ণ স্ক্রিপ্ট

পরীক্ষার ডেটা উত্পন্ন করার জন্য এবং এই জাতীয় দৃশ্যপটের কোনওটি সম্পাদন করতে সম্পূর্ণ স্ক্রিপ্টগুলির জন্য এই পাস্তবিনটি দেখুন । নোট করুন যে আপনাকে অবশ্যই একটি ডাটাবেস ব্যবহার করতে হবে যা SIMPLE পুনরুদ্ধারের মডেলটিতে রয়েছে


ব্যবসায়ের প্রসঙ্গ

আমরা আধা ঘন ঘন লক্ষ লক্ষ সারির ডেটা ঘুরে বেড়াচ্ছি এবং কার্যকর করার সময় এবং ডিস্ক আই / ও লোড উভয় ক্ষেত্রেই এই অপারেশনগুলি যথাসম্ভব দক্ষ হওয়া জরুরি। আমরা প্রাথমিকভাবে এই ধারণাটির আওতায় ছিলাম যে একটি হিপ টেবিল তৈরি করা এবং INSERT...WITH (TABLOCK)এটি করা ভাল উপায় ছিল তবে এখন আমরা কম আত্মবিশ্বাসী হয়েছি যে আমরা একটি বাস্তব উত্পাদন দৃশ্যে উপরে প্রদর্শিত পরিস্থিতিটি পর্যবেক্ষণ করেছি (আরও জটিল প্রশ্নগুলি না থাকলেও সরলীকৃত সংস্করণ এখানে)।

উত্তর:


7

দ্বিতীয় কোয়েরি কেন ন্যূনতম লগিংয়ের জন্য যোগ্যতা অর্জন করে না?

ন্যূনতম লগিং দ্বিতীয় ক্যোয়ারির জন্য উপলভ্য , তবে ইঞ্জিন রানটাইমে এটি ব্যবহার না করা বেছে নেয়।

একটা হল সর্বনিম্ন থ্রেশহোল্ড জন্য INSERT...SELECTযা নীচের এটি বাল্ক লোড অপ্টিমাইজেশন ব্যবহার না করার পছন্দ করে। বাল্ক রোসেট অপারেশন স্থাপনের সাথে জড়িত একটি ব্যয় রয়েছে এবং কেবলমাত্র কয়েকটি সারি বাল্ক-সন্নিবেশ করানোর ফলে দক্ষ স্থান ব্যবহারের ফলস্বরূপ দেখা যায় না।

পরিস্থিতি উন্নয়নে কী করা যায়?

এমন অনেকগুলি পদ্ধতির একটি ব্যবহার করুন (উদাঃ SELECT INTO) যার এই প্রান্তিকতা নেই। বিকল্পভাবে, আপনি থ্রোসোল্ডের জন্য সারি / পৃষ্ঠাগুলির আনুমানিক সংখ্যা বাড়ানোর জন্য উত্স ক্যোয়ারীটি কোনওভাবে পুনরায় লিখতে সক্ষম হবেন INSERT...SELECT

আরও দেখুন জিওফ স্ব-উত্তর আরো দরকারী তথ্য জন্য।


সম্ভবত আকর্ষণীয় ট্রিভিয়া: বাল্ক লোডিং অপ্টিমাইজেশান ব্যবহার করা হয় না তখনইSET STATISTICS IO লক্ষ্য সারণির জন্য যৌক্তিক পাঠের প্রতিবেদন করা হয়


5

আমি আমার নিজের পরীক্ষার ছদ্মবেশ নিয়ে সমস্যাটি পুনরায় তৈরি করতে সক্ষম হয়েছি:

USE test;

CREATE TABLE dbo.SourceGood
(
    SourceGoodID INT NOT NULL
        CONSTRAINT PK_SourceGood
        PRIMARY KEY CLUSTERED
        IDENTITY(1,1)
    , SomeData VARCHAR(384) NOT NULL
);

CREATE TABLE dbo.SourceBad
(
    SourceBadID INT NOT NULL
        CONSTRAINT PK_SourceBad
        PRIMARY KEY CLUSTERED
        IDENTITY(-2147483647,1)
    , SomeData VARCHAR(384) NOT NULL
);

CREATE TABLE dbo.InsertTest
(
    SourceBadID INT NOT NULL
        CONSTRAINT PK_InsertTest
        PRIMARY KEY CLUSTERED
    , SomeData VARCHAR(384) NOT NULL
);
GO

INSERT INTO dbo.SourceGood WITH (TABLOCK) (SomeData) 
SELECT TOP(5000000) o.name + o1.name + o2.name
FROM syscolumns o
    , syscolumns o1
    , syscolumns o2;
GO

ALTER DATABASE test SET AUTO_UPDATE_STATISTICS OFF;
GO

INSERT INTO dbo.SourceBad WITH (TABLOCK) (SomeData)
SELECT TOP(5000000) o.name + o1.name + o2.name
FROM syscolumns o
    , syscolumns o1
    , syscolumns o2;
GO

ALTER DATABASE test SET AUTO_UPDATE_STATISTICS ON;
GO

BEGIN TRANSACTION;

INSERT INTO dbo.InsertTest WITH (TABLOCK)
SELECT *
FROM dbo.SourceGood;

SELECT * FROM sys.dm_tran_database_transactions;

/*
database_transaction_log_record_count
472 
database_transaction_log_bytes_used
692136
*/

COMMIT TRANSACTION;


BEGIN TRANSACTION;

INSERT INTO dbo.InsertTest WITH (TABLOCK)
SELECT *
FROM dbo.SourceBad;

SELECT * FROM sys.dm_tran_database_transactions;

/*
database_transaction_log_record_count   
5000003 
database_transaction_log_bytes_used
642699256
*/

COMMIT TRANSACTION;

এটি প্রশ্নটি উত্থাপন করে, কেন ন্যূনতম-লগ ইন করা অপারেশন চালানোর আগে উত্স টেবিলের পরিসংখ্যান আপডেট করে সমস্যাটি "সংশোধন" করবেন না?

TRUNCATE TABLE dbo.InsertTest;
UPDATE STATISTICS dbo.SourceBad;

BEGIN TRANSACTION;

INSERT INTO dbo.InsertTest WITH (TABLOCK)
SELECT *
FROM dbo.SourceBad;

SELECT * FROM sys.dm_tran_database_transactions;

/*
database_transaction_log_record_count
472
database_transaction_log_bytes_used
692136
*/

COMMIT TRANSACTION;

2
আসল কোডে, একটি জটিল SELECTবিবৃতি রয়েছে যার সাথে অনেকগুলি যোগ দেয় এবং এর ফলাফল নির্ধারণ করে INSERT। এইগুলিতে চূড়ান্ত টেবিল সন্নিবেশকারী অপারেটরের (যা আমি খারাপ UPDATE STATISTICSকলের মাধ্যমে রেপ্রো স্ক্রিপ্টে সিমুলেটেড করেছি) এর জন্য দুর্বল কার্ডিনালিটির অনুমান উত্পাদন করি UPDATE STATISTICSএবং সমস্যাটি সমাধানের জন্য একটি আদেশ জারি করার মতো এটি এতটা সহজ নয় । আমি সম্পূর্ণরূপে সম্মত হই যে ক্যোয়ারীটি সহজ করে তোলা যাতে কার্ডিনালিটি এসটিমেটরের পক্ষে এটি বোঝা আরও ভাল হয় যে কোনও ভাল পদ্ধতির হতে পারে তবে প্রদত্ত জটিল ব্যবসার যুক্তি বাস্তবায়ন করা কোনও ট্রিভাল নয়।
জেফ প্যাটারসন

এটি পরীক্ষা করার জন্য আমার কাছে এসকিউএল সার্ভার ২০১৪ উদাহরণ নেই, তবে এসকিউএল সার্ভারকে চিহ্নিতকরণ 2014 নতুন কার্ডিনালিটি অনুমানের সমস্যাগুলি এবং সার্ভিস প্যাক 1 এর উন্নতিতে নতুন কার্ডিনালিটি অনুমানকারী সক্ষম করতে অন্যদের মধ্যে ট্রেস পতাকা 4130 সক্ষম করার বিষয়ে কথা বলা হয়েছে। আপনি কি চেষ্টা করেছেন?
ম্যাক্স ভার্নন

ভাল ধারণা, কিন্তু এটি কোন উপকারে আসেনি। আমি কেবল টিএফ 4199, টিএফ 610 (ন্যূনতম লগিং শর্তগুলি আলগা করে) চেষ্টা করেছি এবং উভয়ই একসাথে (আরে, কেন নয়?), তবে দ্বিতীয় পরীক্ষার প্রশ্নের জন্য কোনও পরিবর্তন নেই।
জেফ প্যাটারসন

4

সারিগুলির আনুমানিক সংখ্যা বাড়ানোর জন্য উত্স ক্যোয়ারীটি কোনওভাবে পুনরায় লিখুন

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

-- Create a dummy table that SQL Server thinks has a million rows
CREATE TABLE dbo.emptyTableWithMillionRowEstimate (
    n INT PRIMARY KEY
)
GO
UPDATE STATISTICS dbo.emptyTableWithMillionRowEstimate
WITH ROWCOUNT = 1000000
GO

-- Concatenate this table into the final rowset:
INSERT INTO dbo.minimalLoggingTest WITH (TABLOCK) (n)
SELECT n
-- Any table/view/sub-query that correctly estimates that it will generate 5MM rows
FROM dbo.fiveMillionNumbersBadEstimate
-- Add in dummy rowset to ensure row estimate is high enough for bulk load optimization
UNION ALL
SELECT NULL FROM dbo.emptyTableWithMillionRowEstimate
OPTION (MAXDOP 1)

ফাইনাল টেকওয়েস

  1. SELECT...INTOনূন্যতম লগিংয়ের প্রয়োজন হলে ওয়ান-টাইম sertোকানো ক্রিয়াকলাপগুলির জন্য ব্যবহার করুন । পল যেমন উল্লেখ করেছেন, সারি অনুমান নির্বিশেষে এটি ন্যূনতম লগিং নিশ্চিত করবে
  2. যেখানেই সম্ভব, ক্যোয়ারী অপ্টিমাইজার কার্যকরভাবে বলতে পারে এমন একটি সহজ পদ্ধতিতে ক্যোয়ারী লিখুন। একাধিক টুকরো টুকরো করে কোনও ক্যোয়ারী ভাঙা সম্ভব হতে পারে, উদাহরণস্বরূপ, একটি মধ্যবর্তী টেবিলের উপর পরিসংখ্যান তৈরি করার অনুমতি দেওয়ার জন্য।
  3. আপনার যদি এসকিউএল সার্ভার 2014 এ অ্যাক্সেস থাকে তবে এটি আপনার কোয়েরিতে চেষ্টা করে দেখুন; আমার প্রকৃত উত্পাদনের ক্ষেত্রে, আমি কেবল এটি ব্যবহার করে দেখেছি এবং নতুন কার্ডিনালিটি অনুমানটি অনেক বেশি (এবং আরও ভাল) অনুমান করেছে; কোয়েরিটি তখন ন্যূনতমভাবে লগ করা হয়েছিল। তবে আপনার যদি এসকিউএল 2012 এবং এর আগেরটির সমর্থন প্রয়োজন হয় তবে এটি সহায়ক নাও হতে পারে।
  4. আপনি যদি মরিয়া হয়ে থাকেন তবে এর মতো হ্যাকি সমাধানগুলি প্রয়োগ করতে পারে!

সম্পর্কিত একটি নিবন্ধ

পল হোয়াইট এর মে মে ব্লগ পোস্ট INSERT এর সাথে ন্যূনতম লগিং… হিপ টেবিলগুলিতে নির্বাচন করুন এই তথ্যের কিছু আরও বিস্তারিতভাবে কভার করে।

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