ডেটা গুদামজাত করার দৃশ্যে আমার কি "অটো আপডেটের পরিসংখ্যান" অক্ষম করা উচিত?


12

এসকিউএল সার্ভারে আমার 200 জিবি ডেটা গুদাম রয়েছে।

আমি কিছু প্রশ্নের জন্য সত্যিই ধীর মৃত্যুদন্ড কার্যকর করার অভিজ্ঞতা পেয়েছি; উদাহরণস্বরূপ একটি deleteসহ একটি সাধারণ প্রশ্নের জন্য 12 ঘন্টা inner join

মৃত্যুদণ্ড কার্যকর করার পরিকল্পনা নিয়ে কিছু গবেষণা করার পরে, আমি WITH FULLSCANবিকল্পটি ব্যবহার করে ক্যোয়ারীতে জড়িত 2 টি সারণীর পরিসংখ্যান আপডেট করেছি ।

ক্যোয়ারী এখন এক সেকেন্ডেরও কম সময়ে কার্যকর করা হয়েছে, সুতরাং দেখা যাচ্ছে যে পরিসংখ্যানগুলি টু ডেট ছিল না।

আমি auto update statisticsডেটাবেসটি নিষ্ক্রিয় করার এবং UPDATE STATISTICSডেটা গুদাম লোড হওয়ার পরে ম্যানুয়ালি চালানোর কথা বিবেচনা করছি । ডেটা গুদামটি একটি উত্স ইআরপি সিস্টেম থেকে প্রতিদিন, রাতে বাড়ানো হয়।

আমি কি auto update statisticsডেটা গুদামজাতীয় পরিস্থিতিতে ধরে নেওয়া সঠিক ? পরিবর্তে, ডেটা লোড হওয়ার পরে পরিসংখ্যানগুলিতে ম্যানুয়ালি আপডেট করা কি আরও বেশি অর্থবোধ করে?


এটি পরিসংখ্যান সম্পর্কে খুব ভাল পড়া: সহজ-talk.com/sql/performance/… আমরা 1TB ডিবিতে পরিসংখ্যান আপডেট করার জন্য ওলার সমাধান ola.hallengren.com/… ব্যবহার করে একটি দৈনিক কাজও চালাচ্ছি । আমি অটো আপডেটের পরিসংখ্যান বিকল্পটি অক্ষম করব না।
জয় ওয়াকার

1
এটি আপনার টেবিলগুলিতে কতগুলি রেকর্ড রয়েছে এবং আপনি একটি ব্যাচে কতটা যুক্ত করেন তার উপর এটি অনেকটা নির্ভর করে। 1 বি সারির টেবিলটিতে যেখানে আপনি একটি রাতে 20 মিটার সারি যুক্ত করেন, আপনার পরিসংখ্যান প্রতি 10 দিন আপডেট করা হবে যা দুর্দান্ত নয়।
জেএনকে

2
শুধু এফওয়াইআই - পরিসংখ্যান আপডেটের জন্য প্রান্তিক পরিবর্তন 20% থেকে গতিশীল শতাংশ হারে পরিবর্তন করার জন্য একটি ট্রেস পতাকা (2371) রয়েছে। এখানে আরও দেখুন: ব্লগস.এমএসডন.কম
বি

খুব তথ্যমূলক লিঙ্ক, ধন্যবাদ! @ জেএনকে: হ্যাঁ, এটি একটি বড় ডিবি। স্টেজিং টেবিলটিতে 300 মি + সারি রয়েছে এবং আমরা প্রতিদিন 1 মিটার পর্যন্ত 10 মিটারের মধ্যে কিছু সন্নিবেশ করানোর দিনটির উপর নির্ভর করে। এটি নীচের উত্তর দ্বারা প্রস্তাবিত হিসাবে পরিসংখ্যান আরও নিবিড়ভাবে দেখুন, হবে।
saso

উত্তর:


11

যখন পরিসংখ্যানের অটো_আপডেট হয় তখন একটি শ্বেতপত্র রয়েছে । পরিসংখ্যানগুলিতে স্বয়ংক্রিয় আপডেটগুলি দেখার জন্য এখানে মূল পয়েন্টগুলি রয়েছে:

  • সারণির আকার 0 থেকে> 0 টি সারি (পরীক্ষা 1) এ চলে গেছে।
  • পরিসংখ্যান সংগ্রহ করার সময় সারণীতে সারিগুলির সংখ্যা 500 বা তারও কম ছিল এবং পরিসংখ্যান অবজেক্টের শীর্ষস্থানীয় কলামের কলমডাক্টর তখন থেকে 500 টিরও বেশি পরিবর্তিত হয়েছিলেন (পরীক্ষা 2)।
  • পরিসংখ্যান সংগ্রহ করার সময় সারণিতে 500 টিরও বেশি সারি ছিল, এবং পরিসংখ্যানের অবজেক্টের শীর্ষস্থানীয় কলামের কলমডাক্টর টেবিলে সারি সংখ্যার 500 + 20% এর বেশি পরিবর্তিত হয়েছিলেন (পরিসংখ্যান 3) ।

সুতরাং @ জেএনকে একটি মন্তব্যে এই বিষয়টি উল্লেখ করেছে যে আপনার যদি কোনও টেবিলে ১ বিলিয়ন সারি থাকে, তবে আপডেটটি ট্রিগার করার জন্য আপনার কাছে পরিসংখ্যানের প্রথম কলামে ২০,০০,৫০০০ লেখার দরকার আছে।

আসুন নিম্নলিখিত কাঠামো গ্রহণ করা যাক:

CREATE TABLE dbo.test_table (
    test_table_id INTEGER IDENTITY(1,1) NOT NULL, 
    test_table_value VARCHAR(50), 
    test_table_value2 BIGINT, 
    test_table_value3 NUMERIC(10,2)
);

CREATE CLUSTERED INDEX cix_test_table ON dbo.test_table (test_table_id, test_table_value);

এখন আমরা পরিসংখ্যান জমি মধ্যে কি ঘটেছে তা দেখতে পরীক্ষা করতে পারেন।

select * 
    from sys.stats
        where object_id = OBJECT_ID('dbo.test_table')

stat_container

যাইহোক, এটি একটি অর্থবহ পরিসংখ্যানগত বস্তু কিনা তা দেখতে আমাদের দরকার:

dbcc show_statistics('dbo.test_table',cix_test_table)

বারলেখ

সুতরাং এই পরিসংখ্যান আপডেট করা হয়নি। এর কারণ এটি দেখে মনে হচ্ছে পরিসংখ্যানগুলি কোনও আপডেট না হওয়া অবধি আপডেট হয় না SELECTএবং তারপরেও SELECTএসিকিউএল সার্ভারের হিস্টোগ্রামের মধ্যে যা আছে তার বাইরে পড়তে হয়। এখানে একটি পরীক্ষা স্ক্রিপ্ট যা আমি এটি পরীক্ষা করতে দৌড়েছি:

    CREATE TABLE test_table (
        test_table_id INTEGER IDENTITY(1,1) NOT NULL, 
        test_table_value VARCHAR(50), 
        test_table_value2 BIGINT, 
        test_table_value3 NUMERIC(10,2)
    );

    CREATE CLUSTERED INDEX cix_test_table ON test_table (test_table_id, test_table_value);

    ALTER TABLE test_table ADD CONSTRAINT pk_test_table PRIMARY KEY  (test_table_id)

    SELECT * 
        FROM sys.stats
            WHERE object_id = OBJECT_ID('dbo.test_table')

    --DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table)
    DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;

declare @test int = 0

WHILE @test < 1
    BEGIN
        INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
            ('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
        SET @test = @test + 1;
    END

SELECT 'one row|select < 1', * FROM test_table WHERE test_table_id < 1;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;

SET @test = 1

WHILE @test < 500
    BEGIN
        INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
            ('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
        SET @test = @test + 1;
    END

SELECT '100 rows(add 99)|select < 100',* FROM test_table WHERE test_table_id < 100;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
--get the table up to 500 rows/changes
WHILE @test < 500
    BEGIN
        INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
            ('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
        SET @test = @test + 1;
    END
SELECT '500 rows(add 400)|select < 100',* FROM test_table WHERE test_table_id < 100;
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
SELECT '500 rows(add 400)|select < 500',* FROM test_table WHERE test_table_id < 500;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
--bump it to 501
SET @test = 500;
WHILE @test < 501
    BEGIN
        INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
            ('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
        SET @test = @test + 1;
    END


SELECT '501 rows(add 1)|select < 501',* FROM test_table WHERE test_table_id < 501;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;

--bump it to 600
SET @test = 501;
WHILE @test < 600
    BEGIN
        INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
            ('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
        SET @test = @test + 1;
    END

SELECT '600 rows (add 100)|select < 600',* FROM test_table WHERE test_table_id < 600;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;

--bump it to 700
SET @test = 600;
WHILE @test < 700
    BEGIN
        INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
            ('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
        SET @test = @test + 1;
    END

SELECT '700 rows (add 100)|select < 700', * FROM test_table WHERE test_table_id < 700;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;

--bump it to 1200
SET @test = 700;
WHILE @test < 1200
    BEGIN
        INSERT INTO test_table (test_table_value,test_table_value2,test_table_value3) VALUES
            ('stats test' + CAST(@test AS VARCHAR(10)),@test, @test)
        SET @test = @test + 1;
    END

SELECT '1200 rows (add 500)|select < 1200',* FROM test_table WHERE test_table_id < 1200;
--DBCC SHOW_STATISTICS('dbo.test_table',pk_test_table);
DBCC SHOW_STATISTICS('dbo.test_table',cix_test_table) WITH STAT_HEADER;
--DROP TABLE test_table

অন্ধভাবে অটো_আপডেটের পরিসংখ্যানগুলি অক্ষম করার পরিবর্তে আমি আপনার ডেটা সেটটি স্কিউয়ের জন্য পরীক্ষা করার চেষ্টা করব। যদি আপনার ডেটা উল্লেখযোগ্য স্কিউ প্রদর্শন করে, তবে আপনাকে ফিল্টার করা পরিসংখ্যান তৈরির বিষয়ে বিবেচনা করতে হবে এবং তারপরে সিদ্ধান্ত নিতে হবে যে ম্যানুয়ালি পরিসংখ্যান আপডেটগুলি পরিচালনা করা সঠিক ক্রিয়া।

স্কিউ জন্য বিশ্লেষণ করতে আপনার পরীক্ষা করতে চান এমন নির্দিষ্ট স্ট্যাটাস / সূচক সংমিশ্রণে DBCC SHOW_STATISTICS(<stat_object>, <index_name>);(উপরের স্ক্রিপ্টে WITH STAT_HEADER) চালানো দরকার । আপনার স্কিউতে চোখের ছোঁড়ার একটি দ্রুত উপায় হিস্টোগ্রামের তৃতীয় ফলাফল (তৃতীয় ফলাফল সেট) এবং আপনার মধ্যে তারতম্য পরীক্ষা করে দেখানো হবে EQ_ROWS। যদি এটি মোটামুটি সামঞ্জস্য হয় তবে আপনার স্কিউ ন্যূনতম। এটি ধাপে ধাপে বাড়ানোর জন্য, আপনি RANGE_ROWSকলামটি দেখুন এবং সেখানে তারতম্যটি দেখুন যেহেতু প্রতিটি পদক্ষেপের মধ্যে কতগুলি সারি বিদ্যমান তা পরিমাপ করে। শেষ অবধি, আপনি [All density]ফলাফলটি DENSITY_VECTOR(দ্বিতীয় ফলাফল সেট) থেকে নিতে পারেন [Rows Sampled]এবং এটি STAT_HEADER(প্রথম ফলাফল সেট) এর মান অনুসারে গুন করতে পারেন এবং দেখুন যে কলামে কোনও প্রশ্নের জন্য গড় প্রত্যাশাটি কী হবে। আপনি সেই গড়টিকে আপনার সাথে তুলনা করুনEQ_ROWS এবং যদি এমন অনেকগুলি জায়গা থাকে যেখানে এটির উল্লেখযোগ্যভাবে পরিবর্তিত হয়, তবে আপনি স্কিউ পেয়ে গেছেন।

যদি আপনি দেখতে পান যে আপনার স্কিউ আছে, তবে আপনাকে খুব উচ্চতর রেঞ্জগুলির উপর এমন কিছু ফিল্টার পরিসংখ্যান তৈরি করার বিষয়টি বিবেচনা করা উচিত RANGE_ROWSযাতে আপনি সেই মানগুলি সম্পর্কে আরও ভাল অনুমানের জন্য একটি অতিরিক্ত পদক্ষেপ দিতে পারেন।

একবার আপনার এই ফিল্টার করা পরিসংখ্যানগুলি স্থানে রাখলে আপনি নিজেই পরিসংখ্যান আপডেট করার সম্ভাবনাটি দেখতে পারেন।


বিস্তৃত উত্তরের জন্য আপনাকে ধন্যবাদ। আমার কাছে পরিসংখ্যানগুলির সাথে এতটা অভিজ্ঞতা নেই এবং আমি ভেবেছিলাম এটি আরও জটিল বলে মনে হয়। অবশ্যই নিবিড়ভাবে নজর রাখবে এবং আপনার গাইডলাইন অনুসরণ করবে।
saso
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.