ভারচারের (সর্বাধিক) কারণে টেম্পডবিতে ছড়িয়ে বাছাই করুন


10

32 গিগাবাইট সহ একটি সার্ভারে আমরা এসকিউএল সার্ভার 2014 এসপি 2 চালিয়ে যাচ্ছি 25 গিগাবাইটের সর্বোচ্চ মেমরির সাথে আমাদের দুটি টেবিল রয়েছে, এখানে আপনি উভয় টেবিলের একটি সরল কাঠামো পেয়েছেন:

CREATE TABLE [dbo].[Settings](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [resourceId] [int] NULL,
    [typeID] [int] NULL,
    [remark] [varchar](max) NULL,
    CONSTRAINT [PK_Settings] PRIMARY KEY CLUSTERED ([id] ASC)
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Resources](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [resourceUID] [int] NULL,
 CONSTRAINT [PK_Resources] PRIMARY KEY CLUSTERED ([id] ASC)
) ON [PRIMARY]
GO

নিম্নলিখিত অ ক্লাস্টারযুক্ত সূচী সহ:

CREATE NONCLUSTERED INDEX [IX_UID] ON [dbo].[Resources]
(
    [resourceUID] ASC
)

CREATE NONCLUSTERED INDEX [IX_Test] ON [dbo].[Settings]
(
    [resourceId] ASC,
    [typeID] ASC
)

ডাটাবেসটি compatibility level120 দিয়ে কনফিগার করা হয়েছে ।

আমি যখন এই কোয়েরিটি চালাচ্ছি তখন সেখানে স্পিল রয়েছে tempdb। এইভাবেই আমি কোয়েরিটি কার্যকর করি:

exec sp_executesql N'
select r.id,remark
FROM Resources r
inner join Settings on resourceid=r.id
where resourceUID=@UID
ORDER BY typeID',
N'@UID int',
@UID=38

[remark]ক্ষেত্রটি নির্বাচন না করা হলে কোনও স্পিল ঘটে না। আমার প্রথম প্রতিক্রিয়াটি হ'ল নেস্টেড-লুপ অপারেটরে আনুমানিক সারি সংখ্যা কম হওয়ার কারণে স্পিলগুলি ঘটেছে ills

সুতরাং আমি সেটিংস টেবিলটিতে 5 তারিখের সময় এবং 5 পূর্ণসংখ্যা কলাম যুক্ত করব এবং সেগুলি আমার নির্বাচিত বিবৃতিতে যুক্ত করব। যখন আমি কোয়েরিটি কার্যকর করি তখন কোনও স্পিল ঘটছে না।

কেবল যখন [remark]নির্বাচিত হবে তখন কেন ছড়িয়ে পড়ছে ? এটি সম্ভবত এটির সাথে কিছু করার আছে varchar(max)। স্পিলিং এড়াতে আমি কী করতে পারি tempdb?

OPTION (RECOMPILE)ক্যোয়ারিতে যুক্ত করা কোনও তফাত করে না।


আপনি চেষ্টা করতে পারেন select r.id, LEFT(remark, 512)(বা বোধগম্য স্ট্রিংয়ের দৈর্ঘ্য যাই হোক না কেন)।
মোস্তাক্সিয়ো

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

উত্তর:


10

এখানে বেশ কয়েকটি সম্ভাব্য কাজের ক্ষেত্র হতে চলেছে।

আপনি ম্যানুয়ালি মেমরি অনুদানটি সামঞ্জস্য করতে পারেন , যদিও আমি সম্ভবত সেই পথে যেতে চাই না।

আপনি সর্বাধিক দৈর্ঘ্যের কলামটি ধরার আগে, বাছাইটিকে নীচের দিকে ঠেলে দিতে একটি সিটিই এবং শীর্ষগুলিও ব্যবহার করতে পারেন। এটি নীচের মত কিছু হবে।

WITH CTE AS (
SELECT TOP 1000000000 r.ID, s.ID AS ID2, s.typeID
FROM Resources r
inner join Settings s on resourceid=r.id
where resourceUID=@UID
ORDER BY s.typeID
)
SELECT c.ID, ca.remark
FROM CTE c
CROSS APPLY (SELECT remark FROM dbo.Settings s WHERE s.id = c.ID2) ca(remark)
ORDER BY c.typeID

প্রুফ অফ কনসেপ্ট ডিবিফল্ল iddle এখানে । নমুনা তথ্য এখনও প্রশংসা করা হবে!

আপনি যদি পল হোয়াইটের একটি দুর্দান্ত বিশ্লেষণ পড়তে চান তবে এখানে পড়ুন।


7

কেবল যখন [মন্তব্য] নির্বাচন করা হয় তখন কেন ছড়িয়ে পড়ে?

আপনি যখন এই কলামটি অন্তর্ভুক্ত করবেন তখন স্পিলটি ঘটছে কারণ আপনি বড় স্ট্রিং ডেটা বাছাই করার জন্য যথেষ্ট পরিমাণে মেমরি অনুদান পান না।

আপনি যথেষ্ট পরিমাণে মেমোরি অনুদান পাবেন না কারণ সারিগুলির প্রকৃত সংখ্যাটি সারিগুলির আনুমানিক সংখ্যার চেয়ে 10x বেশি (আনুমানিক 1,302 বনাম 126)।

অনুমান কেন বন্ধ? এসকিউএল সার্ভার কেন মনে করে যে ডিবোতে কেবল একটি সারি রয়েছে resourceid? 38 টির সাথে সেটিংগুলি ?

এটি কোনও পরিসংখ্যানের সমস্যা হতে পারে, যা আপনি চালিয়ে যাচাই করতে পারেন DBCC SHOW_STATISTICS('dbo.Settings', 'IX_Test')এবং সেই হিস্টোগ্রাম পদক্ষেপের জন্য গণনাগুলি দেখতে পারেন। তবে কার্যনির্বাহী পরিকল্পনার থেকে বোঝা যাচ্ছে যে পরিসংখ্যানগুলি যতটা সম্ভব সম্পূর্ণ এবং আধুনিক they

যেহেতু পরিসংখ্যানগুলি সহায়তা করছে না, আপনার সেরা বাজি সম্ভবত একটি কোয়েরি পুনর্লিখন - যা ফরেস্ট তার উত্তরে has েকে রেখেছে


3

আমার কাছে এটি উপস্থিত হয় যে whereক্যোয়ারির ধারাটি সমস্যাটি দিচ্ছে, এবং এটি যদি কম OPTION(RECOMPILE)ব্যবহার করা হয় তবে কম অনুমানের কারণ ।

আমি কিছু পরীক্ষার ডেটা তৈরি করেছি এবং শেষ পর্যন্ত দুটি সমাধান নিয়ে এসেছি, IDক্ষেত্রটি resourcesহয় একটি ভেরিয়েবলের (যদি এটি সর্বদা অনন্য থাকে) বা একটি টেম্প টেবিল থেকে সংগ্রহ করে থাকে, যদি আমাদের একের বেশি থাকতে পারে ID

বেস পরীক্ষার রেকর্ড

SET NOCOUNT ON
DECLARE @i int= 1;
WHILE @i <= 10000
BEGIN
INSERT INTO [dbo].[Settings]([resourceId],[typeID],remark)
VALUES(@i,@i,'KEPT THESE VALUES OUT BECAUSE IT WOULD CLUTTER THE EXAMPLES, VALUES OVER 8000 Chars entered here'); -- 23254 character length on each value
INSERT INTO  [dbo].[Resources](resourceUID)
VALUES(@i);
SET @i += 1;
END

ওপির মতো প্রায় আনুমানিক ফলাফলসীমার জন্য 'সিক' মানগুলি সন্নিবেশ করান (১৩০০ রেকর্ডস)

INSERT INTO  [dbo].[Settings]([resourceId],[typeID],remark)
VALUES(38,38,'KEPT THESE VALUES OUT BECAUSE IT WOULD CLUTTER THE EXAMPLES, VALUES OVER 8000 Chars entered here')
GO 1300

ওপিকে ম্যাচ করার জন্য কমপ্যাট এবং আপডেটের পরিসংখ্যান পরিবর্তন করুন

ALTER DATABASE StackOverflow SET COMPATIBILITY_LEVEL = 120;
UPDATE STATISTICS settings WITH FULLSCAN;
UPDATE STATISTICS resources WITH FULLSCAN;

মূল ক্যোয়ারী

exec sp_executesql N'
select r.id
FROM Resources r
inner join Settings on resourceid=r.id
where resourceUID=@UID
ORDER BY typeID',
N'@UID int',
@UID=38

আমার অনুমানগুলি আরও খারাপ , এক অনুমান সারি সহ, যখন ১৩০০ ফেরত পাওয়া যায়। এবং ওপি যেমন বলেছে, আমি যুক্ত করলে তাতে কিছু আসে যায় নাOPTION(RECOMPILE)

একটি গুরুত্বপূর্ণ বিষয় লক্ষণীয়, হ'ল আমরা যখন ক্লজটি থেকে অনুমান করলাম তখন অনুমানগুলি 100% সঠিক, যা প্রত্যাশা করা হয় যেহেতু আমরা উভয় সারণীতে সমস্ত ডেটা ব্যবহার করছি।

আমি সূচিগুলিকে কেবল পূর্ববর্তী ক্যোয়ারির মতো একই বিষয়গুলি ব্যবহার করার বিষয়টি নিশ্চিত করতে বাধ্য করেছিলাম, বিষয়টি প্রমাণ করতে

exec sp_executesql N'
select r.id,remark
FROM Resources r with(index([IX_UID]))
inner join Settings WITH(INDEX([IX_Test])) 
on resourceid=r.id
ORDER BY typeID',
N'@UID int',
@UID=38

প্রত্যাশিত হিসাবে, ভাল অনুমান।

সুতরাং, আরও ভাল অনুমানের জন্য আমরা কী পরিবর্তন করতে পারি তবে এখনও আমাদের মূল্যবোধগুলি সন্ধান করতে পারি?

যদি @ নির্দেশটি অনন্য, যেমন যেমন ওপি দিয়েছে, আমরা idযে এককটি resourcesভেরিয়েবল থেকে ফেরত পেয়েছিলাম তা রাখতে পারি, তারপরে সেই বিকল্পটি একটি বিকল্প (পুনরুদ্ধার) দিয়ে সন্ধান করতে পারি

DECLARE @UID int =38 , @RID int;
SELECT @RID=r.id from 
Resources r where resourceUID = @UID;

SELECT @uid, remark 
from Settings 
where resourceId = @uid 
Order by typeID
OPTION(RECOMPILE);

যা 100% সঠিক অনুমান দেয়

তবে কি যদি একাধিক রিসোর্সইউড রিসোর্সে থাকে?

কিছু পরীক্ষার ডেটা যুক্ত করুন

INSERT INTO Resources(ResourceUID)
VALUES (38);
go 50

এটি একটি টেম্প টেবিল দিয়ে সমাধান করা যেতে পারে

CREATE TABLE #RID (id int)
DECLARE @UID int =38 
INSERT INTO #RID
SELECT r.id 
from 
Resources r where resourceUID = @UID

SELECT @uid, remark 
from Settings  s
INNER JOIN #RID r
ON r.id =s.resourceId
Order by typeID
OPTION(RECOMPILE)

DROP TABLE #RID

আবার সঠিক অনুমান সহ

এটি আমার নিজস্ব ডেটাসেট, ওয়াইএমএমভি দিয়ে করা হয়েছিল।


Sp_executesql দিয়ে লেখা

একটি পরিবর্তনশীল সহ

exec sp_executesql N'
DECLARE  @RID int;
    SELECT @RID=r.id from 
    Resources r where resourceUID = @UID;

    SELECT @uid, remark 
    from Settings 
    where resourceId = @uid 
    Order by typeID
    OPTION(RECOMPILE);',
N'@UID int',
@UID=38

একটি টেম্প টেবিল সহ

exec sp_executesql N'

CREATE TABLE #RID (id int)

INSERT INTO #RID
SELECT r.id 
from 
Resources r where resourceUID = @UID

SELECT @uid, remark 
from Settings  s
INNER JOIN #RID r
ON r.id =s.resourceId
Order by typeID
OPTION(RECOMPILE)

DROP TABLE #RID',
N'@UID int',
@UID=38

আমার পরীক্ষায় এখনও 100% সঠিক অনুমান

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