25+ মিলিয়ন সারিগুলির জন্য ক্যোয়ারী অনুকূল করা


11

আমি এমএস এসকিউএল ব্যবহার করছি, এবং আমাকে বিভিন্ন মাপদণ্ডে একই টেবিলে বেশ কয়েকটি ক্যুরিয়ার চালাতে হবে। প্রথমে আমি প্রতিটি টিকিটটি মূল টেবিলের দিকে চালিত করেছি যদিও তারা সকলেই কিছু ফিল্টারিং ভাগ করে (যেমন তারিখ, স্থিতি)। এটি অনেক সময় নিয়েছে (প্রায় 2 মিনিট)।

ডেটা সারিগুলিতে সদৃশ রয়েছে এবং সমস্ত সূচি নন-ক্লাস্টার্ড। আমি আমার মানদণ্ডের জন্য 4 টি কলামে আগ্রহী এবং ফলাফলটি সমস্ত প্রশ্নের জন্য কেবল গণনা আউটপুট করে output

কলাম প্রয়োজন: TABLE, FIELD, AFTER, DATE, এবং প্রতিটি উপর একটি সূচক DATEএবং TABLE

আমার প্রয়োজন কেবল ক্ষেত্রগুলি দিয়ে একটি টেম্প টেবিল তৈরি করার পরে, এটি 1:40 মিনিটে নেমে গেছে, যা এখনও খুব খারাপ।

CREATE TABLE #TEMP
(
    TABLE VARCHAR(30) NULL,
    FIELD VARCHAR(30) NULL,
    AFTER VARCHAR(1000) NULL,
    DATE DATETIME,
    SORT_ID INT IDENTITY(1,1)
)
CREATE CLUSTERED INDEX IX_ADT ON #TEMP(SORT_ID)

INSERT INTO #TEMP (TABLE, FIELD, AFTER, DATE)
    SELECT TABLE, FIELD, AFTER, DATE 
    FROM mytbl WITH (NOLOCK)
    WHERE TABLE = 'OTB' AND
    FIELD = 'STATUS'

এটি চালান -> (216598 সারি প্রভাবিত)

যেহেতু সমস্ত প্রশ্নগুলি তারিখের সীমাতে নির্ভর করে না, তাই আমি এটিকে ক্যোয়ারিতে অন্তর্ভুক্ত করি নি। সমস্যাটি হ'ল কেবল সন্নিবেশ করতে 1 মিনিটের বেশি সময় লাগছে । উপরের সন্নিবেশটি 1:19 মিনিট সময় নিয়েছিল

আমি বেশ কয়েকটি প্রশ্নের জন্য এই জাতীয় কিছু চালাতে চাই:

SELECT COUNT(*) AS COUNT
FROM #TEMP
WHERE AFTER = 'R' AND
DATE >= '2014-01-01' AND
DATE <= '2015-01-01'

এটি নির্বাচনের চেয়ে বেশি সন্নিবেশ নিয়ে একটি সমস্যা, তবে টেম্পটির মূল টেবিলের চেয়ে কম সারি রয়েছে যা বেশ কয়েকবার টেবিলের মধ্য দিয়ে যাওয়ার চেয়ে ভাল হতে পারে।

আমি কীভাবে এটি অপ্টিমাইজ করতে পারি?

সম্পাদনা

আমি সাজানো আইডি সরিয়েছি, আমি ভেবেছিলাম সমস্যাটি মূলত নির্বাচিত এবং সন্নিবেশ না দিয়েই ছিল। এটি একটি অনুমান ছিল।

কোনও অনন্য ক্ষেত্র বা সারি নেই বলে আমি কোনও সূচকে অনন্য তৈরি করতে পারি না।

আমি এসকিউএল সার্ভার 2012 ব্যবহার করছি।

সারণী তথ্য : এটি একটি গাদা এবং নিম্নলিখিত স্থানের ব্যবহার রয়েছে:

name    rows        reserved    data        index_size  unused
mytbl   24869658    9204568 KB  3017952 KB  5816232 KB  370384 KB

@ মিকায়েল এরিকসন আমি প্রযোজনার টেবিলগুলি সংশোধন করতে পারি না ..
আতিহ

আপনি যে প্রশ্নগুলি অপ্টিমাইজ করার চেষ্টা করছেন সেগুলি যদি ফর্মের হয় তবে SELECT COUNT(*) AS COUNT FROM original_table WHERE AFTER = 'R' AND DATE >= '2014-01-01' AND DATE < '2015-01-01'আপনি কেন প্রতিটি (ক্যোয়ারী) আলাদাভাবে অনুকূলিত করার চেষ্টা করবেন না? আপনি কি টেবিলে সূচি যোগ করার অনুমতি দিচ্ছেন না?
ypercubeᵀᴹ

2
এটি ধীর কেন হয় তা আপনাকে নির্ধারণ করতে হবে। এটি কি অবরুদ্ধ হচ্ছে? এটি কি টেম্পডিবি বাড়ার জন্য অপেক্ষা করছে? ফাঁসির পরিকল্পনা কি অস্বাভাবিক? "বিশদটি" আমার জিজ্ঞাসা ধীরে ধীরে "কেউ আরও বিশদ ছাড়াই ঠিক করতে পারে না ...
অ্যারন বারট্রান্ড

3
ঠিক আছে, আমার কাছে এটি একটি হারিয়ে যাওয়া কারণের মতো বলে মনে হচ্ছে ( "আমাকে কোনও কিছুরই অনুকূলকরণ করার অনুমতি নেই, তাই প্রতিবার যখন আমাদের কিছু অনুসন্ধান চালানোর দরকার হয় তখন কেবল 200 টুকরো সারি টেম্প টেবিলের মধ্যে চাপ দিন" )। তবে আপনি টেবিল থেকে কলামগুলি TABLEএবং FIELDকলামগুলি সরিয়ে ফেলতে পারেন #temp(সমস্ত সারি TABLE = 'OTB' AND FIELD = 'STATUS'নির্দিষ্ট টেম্প টেবিলের পরে থাকতে পারে))
ypercubeᵀᴹ

2
আমি একটি বিশদ (এবং ভদ্র) মন্তব্য যুক্ত করে একটি সম্পাদনা এবং উন্নতির জন্য জিজ্ঞাসা করেছি। মন্তব্যগুলির জন্য এটিই। আপনি ব্যবহার করছেন এমন এসকিউএল সার্ভারের সংস্করণ (যেমন এসকিউএল সার্ভার 2014) দিয়ে আপনার প্রশ্নটি ট্যাগ করা উচিত। টেবিলের জন্য ডিডিএল খুব সহায়ক হতে পারে ( CREATE TABLEবিবৃতি)। প্রশ্নটি স্পষ্ট না হওয়ায় ডাউন ভোট ছিল।
পল হোয়াইট 9

উত্তর:


12

প্রশ্নটি কীভাবে নির্বাচনের বিবৃতিটি অনুকূল করা যায় সে সম্পর্কে:

SELECT [TABLE], [FIELD], [AFTER], [DATE]
FROM mytbl WITH (NOLOCK)
WHERE [TABLE] = 'OTB' AND
[FIELD] = 'STATUS'

অপ্রয়োজনীয় অনুমানগুলি সরানো এবং অনুমিত dboস্কিমা যুক্ত করা:

SELECT [AFTER], [DATE] 
FROM dbo.mytbl WITH (NOLOCK)
WHERE [TABLE] = 'OTB'
AND FIELD = 'STATUS';

([TABLE],[FIELD]) INCLUDE ([AFTER],[DATE])এসকিউএল সার্ভারের মতো সূচি ব্যতীত দুটি প্রধান বিকল্প রয়েছে:

  1. পুরোপুরি হিপ স্ক্যান করুন (3 জিবি +); অথবা
  2. সারিগুলি মিলছে [TABLE] = 'OTB'এবং [FIELD] = 'STATUS'(ব্যবহার করে IDX6) সন্ধান করুন, তারপরে এবং কলামগুলি পুনরুদ্ধার করতে প্রতি সারিতে একটি হিপ (আরআইডি) অনুসন্ধান করুন ।[AFTER][DATE]

অপ্টিমাইজারটি আরআইডি লুকআপের সাহায্যে হিপ স্ক্যান বা সূচী অনুসন্ধান চয়ন করে কিনা [TABLE] = 'OTB'এবং [FIELD] = 'STATUS'ভবিষ্যদ্বাণীগুলির আনুমানিক নির্বাচনের উপর নির্ভর করে । সন্ধান থেকে সারিগুলির আনুমানিক সংখ্যা বাস্তবতার সাথে মিলছে কিনা তা পরীক্ষা করে দেখুন। যদি তা না হয় তবে আপনার পরিসংখ্যান আপডেট করুন। সূচিটি ব্যবহারের জন্য জোর করে কোনও টেবিলের ইঙ্গিত দিয়ে ক্যোরিটি পরীক্ষা করুন, যদি সেই শর্তটি যথাযথভাবে নির্বাচনী হয় । যদি অপ্টিমাইজার বর্তমানে সূচকটি বেছে নিচ্ছে তবে হ্যাপ স্ক্যান করার জন্য কোনও INDEX(0)বা FORCESCANইঙ্গিত দিয়ে পরীক্ষা সম্পাদন করুন ।

এর বাইরে, আপনি অব্যবহৃত কিছু জায়গা (370MB) সরিয়ে কিছুটা গাদা স্ক্যানের উন্নতি করতে পারেন। এসকিউএল সার্ভার ২০০৮ এ হিপগুলি পুনর্নির্মাণের মাধ্যমে করা যেতে পারে। হিপগুলিতে অব্যবহৃত স্থান প্রায়শই একটি টেবিল লক নেওয়া ছাড়া সঞ্চালিত মোছার ফলাফল (টেবিল লক ছাড়া খালি পৃষ্ঠাগুলি একটি গাদা থেকে বিচ্ছিন্ন হয় না)। প্রায়শই মুছে ফেলার অভিজ্ঞতা থাকা টেবিলগুলি প্রায়শই এই কারণে ক্লাস্টার টেবিল হিসাবে আরও ভাল সঞ্চয় করা হয়।

হিপ স্ক্যানের পারফরম্যান্স নির্ভর করে টেবিলের কতটুকু স্মৃতিতে সঞ্চিত রয়েছে, ডিস্ক থেকে কতটা পড়তে হবে, পৃষ্ঠাগুলি কতটা পূর্ণ, স্থির স্টোরেজের গতি, স্ক্যানটি আই / ও বা সিপিইউ আবদ্ধ কিনা on সমান্তরালতা সাহায্য করতে পারে)।

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

CREATE INDEX index_name
ON dbo.mytbl ([DATE],[AFTER])
WHERE [TABLE] = 'OTB'
AND [FIELD] = 'STATUS';

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


দুঃখিত পল, থাকে: IDX6 nonclustered located on PRIMARY TABLE, FIELD। সম্ভবত এটি আপনার উল্লেখ করা জিনিসগুলিকে বদলে দেবে?
আতিহ

6

আমি মনে করি এখানে সূচকগুলি পরিবর্তনের জন্য একটি মামলা রয়েছে কারণ:

  • আপনার একটি কাজ করতে হবে (এই একাধিক প্রশ্ন)
  • ডেটা গুদাম ভলিউম (25+ মিলিয়ন সারি) এবং
  • একটি কর্মক্ষমতা সমস্যা।

এটি এসকিউএল সার্ভার ২০১২-তে প্রবর্তিত নন-ক্লাস্টারযুক্ত কলামস্টোর সূচীর জন্যও ভাল ব্যবহারের ক্ষেত্রে হবে, অর্থাত্ অনেকগুলি কলাম সহ বৃহত টেবিলে কয়েকটি কলাম সংক্ষিপ্ত / সংহত করে।

যদিও এই সূচিগুলির টেবিলটি কেবল পঠনযোগ্য (পার্টিশন স্যুইচিং ব্যতীত) করার পার্শ্ব-প্রতিক্রিয়া রয়েছে, তারা সঠিক অবস্থার অধীনে সামগ্রিক প্রশ্নের কার্য সম্পাদনকে রূপান্তর করতে পারে। কেবল পঠনযোগ্য দিকটি পরিচালনা করতে পারবেন সূচিগুলি ফেলে রেখে এবং পুনরায় তৈরি করে বা সাধারণ পার্টিশনের সুইচ ডেটাটি টেবিলের মধ্যে।

আপনার সেটআপটি নকল করতে আমি একটি সাধারণ পরীক্ষার কাঠামো সেট আপ করেছি, এবং পারফরম্যান্সে একটি ভাল উন্নতি দেখেছি:

USE tempdb
GO

SET NOCOUNT ON
GO

-- Create a large table
IF OBJECT_ID('dbo.largeTable') IS NOT NULL
DROP TABLE dbo.largeTable
GO
CREATE TABLE dbo.largeTable ( 

    [TABLE] VARCHAR(30) NULL,
    FIELD VARCHAR(30) NULL,
    [AFTER] VARCHAR(1000) NULL,
    [DATE] DATETIME,
    SORT_ID INT IDENTITY(1,1),

    pad VARCHAR(100) DEFAULT REPLICATE( '$', 100 )
)
GO

-- Populate table
;WITH cte AS (
SELECT TOP 100000 ROW_NUMBER() OVER ( ORDER BY ( SELECT 1 ) ) rn
FROM master.sys.columns c1
    CROSS JOIN master.sys.columns c2
    CROSS JOIN master.sys.columns c3
)
INSERT INTO dbo.largeTable ( [TABLE], FIELD, [AFTER], [DATE] )
SELECT 
    x.tableName, 
    y.field,
    z.[after],
    DATEADD( day, rn % 1111, '1 Jan 2012' )
FROM cte c
    CROSS JOIN ( VALUES ( 'OTB' ), ( 'AAA' ), ( 'BBB' ), ( 'CCCC' ) ) x ( tableName )
    CROSS JOIN ( VALUES ( 'STATUS' ), ( 'TIME' ), ( 'POWER' ) ) y ( field )
    CROSS JOIN ( VALUES ( 'R' ), ( 'X' ), ( 'Z' ), ( 'A' ) ) z ( [after] )

CHECKPOINT

GO 5

EXEC sp_spaceused 'dbo.largeTable'
GO

SELECT MIN([DATE]) xmin, MAX([DATE]) xmax, FORMAT( COUNT(*), '#,#' ) records
FROM dbo.largeTable
GO

-- Optionally clear cache for more comparable results; DO NOT RUN ON PRODUCTION SYSTEM!!
--DBCC DROPCLEANBUFFERS
--DBCC FREEPROCCACHE
--GO

DECLARE @startDate DATETIME2 = SYSUTCDATETIME()

SELECT COUNT(*) AS COUNT
FROM dbo.largeTable
WHERE [AFTER] = 'R' 
  AND [DATE] >= '2014-01-01' 
  AND [DATE] <= '2015-01-01'

SELECT DATEDIFF( millisecond, @startDate, SYSUTCDATETIME() ) diff1
GO

-- Add the non-clustered columnstore
CREATE NONCLUSTERED COLUMNSTORE INDEX _cs ON dbo.largeTable ( [TABLE], FIELD, [AFTER], [DATE] )
GO

-- Optionally clear cache for more comparable results; DO NOT RUN ON PRODUCTION SYSTEM!!
--DBCC DROPCLEANBUFFERS
--DBCC FREEPROCCACHE
--GO

-- Check query again
DECLARE @startDate DATETIME2 = SYSUTCDATETIME()

SELECT COUNT(*) AS COUNT
FROM dbo.largeTable
WHERE [AFTER] = 'R' 
  AND [DATE] >= '2014-01-01' 
  AND [DATE] <= '2015-01-01'

SELECT DATEDIFF( millisecond, @startDate, SYSUTCDATETIME() ) diff2
GO

আমার ফলাফল, 6 সেকেন্ড বনাম 0.08 সেকেন্ড:

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

সংক্ষেপে, আপনার বসের সাথে সূচী পরিবর্তন করতে বা কমপক্ষে রাতারাতি এমন কোনও প্রক্রিয়া তৈরি করতে চেষ্টা করুন যেখানে এই রেকর্ডগুলি কেবলমাত্র পঠনযোগ্য রিপোর্টিং টেবিল / ডাটাবেসে খোদাই করা আছে যেখানে আপনি নিজের কাজটি করতে পারেন, এবং সূচীকরণ যুক্ত করুন কাজের চাপের জন্য উপযুক্ত।

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