নির্বাচনী বিবৃতিতে অগ্রগতি


14

আমাদের ইটিএল প্রবাহের একটি দীর্ঘ-চলমান নির্বাচন নির্বাচন-বিবৃতি রয়েছে, এটি ফ্লাইতে একটি টেবিল তৈরি করে এবং কয়েকশ মিলিয়ন রেকর্ডের সাহায্যে এটিকে জনপ্রিয় করে তুলছে।

বিবৃতিটি দেখতে কিছুটা এমন দেখাচ্ছে SELECT ... INTO DestTable FROM SrcTable

পর্যবেক্ষণের উদ্দেশ্যে, আমরা এই বিবৃতিটির অগ্রগতি সম্পর্কে মোটামুটি ধারণা পেতে চাই, যখন এটি কার্যকর করা হচ্ছে (আনুমানিক রাউকাউন্ট, বাইটের লিখিত সংখ্যা, বা অনুরূপ)।

আমরা নিম্নলিখিতগুলি চেষ্টা করেছিলাম কোনও লাভ হয়নি:

-- Is blocked by the SELECT INTO statement:
select count(*) from DestTable with (nolock)

-- Returns 0, 0:
select rows, rowmodctr
from sysindexes with (nolock)
where id = object_id('DestTable')

-- Returns 0:
select rows
from sys.partitions
where object_id = object_id('DestTable')

তদ্ব্যতীত, আমরা লেনদেনটি দেখতে পাচ্ছি sys.dm_tran_active_transactions, তবে আমি প্রদত্ত ক্ষতিগ্রস্থ সারিগুলির গণনা পাওয়ার কোনও উপায় খুঁজে পাইনি transaction_id( @@ROWCOUNTসম্ভবত এর অনুরূপ কিছু , তবে transaction_idযুক্তি হিসাবে)।

আমি বুঝতে পারি যে এসকিউএল সার্ভারে নির্বাচন নির্বাচন-বিবৃতি উভয়ই একটি ডিডিএল এবং একটিতে ডিএমএল বিবৃতি, এবং এর মতো, অন্তর্ভুক্ত টেবিল তৈরি করা একটি লকিং অপারেশন হবে। আমি এখনও মনে করি বিবৃতি চলাকালীন কিছু প্রগতি সম্পর্কিত তথ্য পাওয়ার জন্য অবশ্যই কিছু চতুর উপায় থাকতে হবে।


আপনি যদি বিশ্বব্যাপী টেম্প টেবিল ব্যবহার করেন ## টেবিল, আপনি ইতিমধ্যে লিখিত রেকর্ডের সংখ্যা এবং মোট রেকর্ডের পরিমাণের লিখিত পরিমাণ নির্ধারণের জন্য ## টেবিলের সূচক কলামে গণনা সহ একটি নির্বাচন করতে পারবেন?
কোভগেক

উত্তর:


6

আমি সন্দেহ যে rowsএর মধ্যে sys.partitionsএখনো সংঘটিত হচ্ছে না কারণে 0। তবে এর অর্থ এই নয় যে লেনদেনটি যদি কমিট করে তবে সেখানে কী হবে সে সম্পর্কে এসকিউএল সার্ভার অজানা। মূল কথাটি মনে রাখা দরকার যে সমস্ত অপারেশন প্রথমে বাফার পুল (অর্থাত্ মেমরি) দিয়ে যায়, অপারেশনটির COMMIT বা রোলব্যাককে বিবেচনা না করেই। অতএব, আমরা sys.dm_os_buffer_descriptorsসেই তথ্যের সন্ধান করতে পারি :

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

SELECT  --OBJECT_NAME(sp.[object_id]) AS [TableName], sdobd.*, '---', sp.*, '---', sau.*
       SUM(sdobd.[row_count]) AS [BufferPoolRows],
       SUM(sp.[rows]) AS [AllocatedRows],
       COUNT(*) AS [DataPages]
FROM sys.dm_os_buffer_descriptors sdobd
INNER JOIN  sys.allocation_units sau
        ON sau.[allocation_unit_id] = sdobd.[allocation_unit_id]
INNER JOIN  sys.partitions sp
        ON  (   sau.[type] = 1
            AND sau.[container_id] = sp.[partition_id]) -- IN_ROW_DATA
        OR  (   sau.[type] = 2
            AND sau.[container_id] = sp.[hobt_id]) -- LOB_DATA
        OR  (   sau.[type] = 3
            AND sau.[container_id] = sp.[partition_id]) -- ROW_OVERFLOW_DATA
WHERE   sdobd.[database_id] = DB_ID()
AND     sdobd.[page_type] = N'DATA_PAGE'
AND     sp.[object_id] = (SELECT so.[object_id]
                          FROM   sys.objects so
                          WHERE  so.[name] = 'TestDump')

আপনি যদি বিশদটি দেখতে চান তবে SELECTতালিকার প্রথম সারিতে আইটেমটি নিরবচ্ছিন্ন করুন, বাকি 3 টি লাইন মন্তব্য করুন।

আমি এক সেশনে নিম্নলিখিতটি চালিয়ে পরীক্ষা করেছিলাম এবং তারপরে বার বার অন্য কোষে উপরে কোয়েরি চালিয়েছি।

SELECT so1.*
INTO   dbo.TestDump
FROM   sys.objects so1
CROSS JOIN sys.objects so2
CROSS JOIN sys.objects so3;

1
এটি সৃজনশীল। কেবল একটি সতর্কতা যুক্ত করতে চাই যে একটি বড় বাফার পুলটি গণনা করা খুব ধীর।
usr

1
এটি ধরে নিয়েছে যে বাফার পুল থেকে এখনও কোনও পৃষ্ঠাগুলি উচ্ছেদ করা হয়নি।
মার্টিন স্মিথ

@ মার্টিনস্মিথ পৃষ্ঠাগুলি প্রতিশ্রুতিবদ্ধ হওয়ার আগেই উচ্ছেদ করা যেতে পারে?
সলোমন রুটজকি

5
@ শ্রুতজকি - হ্যাঁ লেনদেন লগে রোলব্যাক করার জন্য প্রয়োজনীয় সমস্ত তথ্য রয়েছে। নোংরা পৃষ্ঠাগুলি ডিস্কে লেখা যেতে পারে - উদাহরণস্বরূপ একটি চেকপয়েন্টে বা আগ্রহী লেখক দ্বারা বিশেষত এই ক্ষেত্রে তারপরে বাফার পুল থেকে সরানো।
মার্টিন স্মিথ

7

পর্যবেক্ষণের উদ্দেশ্যে, আমরা এই বিবৃতিটি কার্যকর করার সময়, এর অগ্রগতি সম্পর্কে মোটামুটি ধারণা পেতে চাই।

এক বন্ধ নাকি চলছে?

এটি যদি এমন কোনও প্রয়োজন হয় যা আগে থেকে অনুমান করা যায় * আপনি ব্যবহার করতে পারেন sys.dm_exec_query_profiles

সংযোগ 1 (সেশন 55)

SET STATISTICS XML ON

SELECT so1.*
INTO   dbo.TestDump
FROM   sys.all_objects so1
CROSS JOIN sys.all_objects so2
CROSS JOIN sys.all_objects so3
CROSS JOIN sys.all_objects so4
CROSS JOIN sys.all_objects so5;

সংযোগ 2

select row_count
from sys.dm_exec_query_profiles
WHERE physical_operator_name = 'Table Insert' 
    AND session_id = 55;

যদি প্যারালালিজম ব্যবহার করাSELECT INTO হয় তবে আপনাকে ফিরে আসা সারির সংখ্যাগুলি যোগ করতে হবে ।

* আপনি এই ডিএমভি ব্যবহার করে যে সেশনটি পর্যবেক্ষণ করতে চান সেটি অবশ্যই SET STATISTICS PROFILE ONবা ব্যবহার করে পরিসংখ্যান সংগ্রহের জন্য সক্ষম করতে হবে SET STATISTICS XML ON। এসএসএমএস থেকে "প্রকৃত" কার্যকরকরণ পরিকল্পনার অনুরোধটিও কাজ করে (কারণ এটি পরের বিকল্পটি সেট করে)।


মনে হচ্ছে আমি ফেব্রুয়ারিতে এটি +1 করতে ভুলে গিয়েছিলাম, তবে আমি এটি সম্পর্কে পুরোপুরি ভুলে যাইনি :)। আমি কেবলমাত্র এই সম্পর্কিত প্রশ্নটিতে এটি ব্যবহার করেছি যেহেতু ওপি কমপক্ষে 2014 এ রয়েছে: dba.stackexchange.com/questions/139191/… এটি নির্দেশ করার জন্য ধন্যবাদ; এটি বেশ কার্যকর ডিএমভি :-)
সলোমন রুটজকি

2
@ শ্রুতজকি হ্যাঁ এটি খুব কার্যকর। এবং এসএসএমএস ২০১
মার্টিন স্মিথ

5

আমি মনে করি না যে সারি গণনা পাওয়ার কোনও উপায় আছে তবে আপনি এটি দেখে কতটা ডেটা লিখেছেন তা অনুমান করতে পারেন:

SELECT writes 
  FROM sys.dm_exec_requests WHERE session_id = <x>;

SELECT COUNT(*) FROM sys.dm_db_database_page_allocations
(<dbid>, OBJECT_ID(N'dbo.newtablename'), 0, NULL, 'LIMITED');

সম্পন্ন হওয়ার সময় গাদা কত পৃষ্ঠাগুলি গ্রহণ করা উচিত সে সম্পর্কে আপনার যদি কোনও ধরণের ধারণা থাকে তবে আপনার% সম্পন্ন করে কাজ করতে সক্ষম হওয়া উচিত। সারণী বড় হওয়ার সাথে সাথে উত্তর কোয়েরি দ্রুত হবে না। এবং উপরোক্ত অধীনটি চালানো সম্ভবত সবচেয়ে নিরাপদ READ UNCOMMITTED(এবং এটি আমি প্রায়শই প্রস্তাব করি না যে কোনও কিছুর জন্য)।


4

আপনি যদি এ INSERTথেকে পরিবর্তন করতে পারেন

SELECT ... INTO DestTable FROM SrcTable

to a

INSERT DestTable SELECT ... FROM SrcTable

তাহলে আপনার select count(*) from DestTable with (nolock)জিজ্ঞাসা কাজ করবে।

যদি এটি সম্ভব না হয় তবে আপনি কোয়েরিটি কতটি লিখেছেন তা নিরীক্ষণ করতে আপনি sp_WhoIsActive (বা ডিএমভিগুলিতে সন্ধান করতে পারেন) ব্যবহার করতে পারেন। এটি একটি বরং রুক্ষ গেজ হবে তবে যদি আপনি সাধারণত লেখার সংখ্যাটি রেখায় থাকেন তবে এটি কার্যকর হতে পারে।

আপনি যদি যুক্ত করেন তবে উপরের সাথে ন্যূনতম লগিং পেতে সক্ষম হবেন ।INSERTWITH (TABLOCK)


এই মন্তব্যের জন্য আপনাকে ধন্যবাদ। আমরা ন্যূনতম লগিং পেতে চাই, এজন্যই আমরা নির্বাচন ... ব্যবহারের পদ্ধতিটি ব্যবহার করি (এবং কারণ আমরা একরকম অলস ...)
ড্যান

1
আপনি INSERTযদি যুক্ত করেন তবে উপরের সাথে ন্যূনতম লগিং পেতে সক্ষম হবেনWITH(TABLOCK)
জেমস অ্যান্ডারসন

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