আমি চেষ্টা করছি যে এসকিউএল সার্ভারকে কোয়েরির জন্য একটি নির্দিষ্ট পরিকল্পনা ব্যবহার করার কৌশল আছে কিনা trick
1. পরিবেশ
আপনার কাছে এমন কিছু ডেটা রয়েছে যা বিভিন্ন প্রক্রিয়ার মধ্যে ভাগ করা আছে তা কল্পনা করুন। সুতরাং, ধরুন আমাদের কিছু পরীক্ষার ফলাফল রয়েছে যা অনেক বেশি জায়গা নেয়। তারপরে, প্রতিটি প্রক্রিয়াটির জন্য আমরা জানি যে কোন বছর / মাসের পরীক্ষার ফলাফল আমরা ব্যবহার করতে চাই।
if object_id('dbo.SharedData') is not null
drop table SharedData
create table dbo.SharedData (
experiment_year int,
experiment_month int,
rn int,
calculated_number int,
primary key (experiment_year, experiment_month, rn)
)
go
এখন, প্রতিটি প্রক্রিয়াটির জন্য আমাদের টেবিলে সংরক্ষণ করা প্যারামিটার রয়েছে
if object_id('dbo.Params') is not null
drop table dbo.Params
create table dbo.Params (
session_id int,
experiment_year int,
experiment_month int,
primary key (session_id)
)
go
2. পরীক্ষার তথ্য
আসুন কিছু পরীক্ষার ডেটা যুক্ত করুন:
insert into dbo.Params (session_id, experiment_year, experiment_month)
select 1, 2014, 3 union all
select 2, 2014, 4
go
insert into dbo.SharedData (experiment_year, experiment_month, rn, calculated_number)
select
2014, 3, row_number() over(order by v1.name), abs(Checksum(newid())) % 10
from master.dbo.spt_values as v1
cross join master.dbo.spt_values as v2
go
insert into dbo.SharedData (experiment_year, experiment_month, rn, calculated_number)
select
2014, 4, row_number() over(order by v1.name), abs(Checksum(newid())) % 10
from master.dbo.spt_values as v1
cross join master.dbo.spt_values as v2
go
৩. ফলাফল আনছে
এখন, এর দ্বারা পরীক্ষার ফলাফল পাওয়া খুব সহজ @experiment_year/@experiment_month
:
create or alter function dbo.f_GetSharedData(@experiment_year int, @experiment_month int)
returns table
as
return (
select
d.rn,
d.calculated_number
from dbo.SharedData as d
where
d.experiment_year = @experiment_year and
d.experiment_month = @experiment_month
)
go
পরিকল্পনাটি সুন্দর এবং সমান্তরাল:
select
calculated_number,
count(*)
from dbo.f_GetSharedData(2014, 4)
group by
calculated_number
ক্যোয়ারী 0 পরিকল্পনা
4. সমস্যা
তবে, ডেটাটিকে কিছুটা জেনেরিক ব্যবহার করতে, আমি আরও একটি ফাংশন রাখতে চাই - dbo.f_GetSharedDataBySession(@session_id int)
। সুতরাং, সহজবোধ্য উপায় স্কালে ফাংশন, অনুবাদ তৈরি করতে হবে @session_id
-> @experiment_year/@experiment_month
:
create or alter function dbo.fn_GetExperimentYear(@session_id int)
returns int
as
begin
return (
select
p.experiment_year
from dbo.Params as p
where
p.session_id = @session_id
)
end
go
create or alter function dbo.fn_GetExperimentMonth(@session_id int)
returns int
as
begin
return (
select
p.experiment_month
from dbo.Params as p
where
p.session_id = @session_id
)
end
go
এবং এখন আমরা আমাদের ফাংশন তৈরি করতে পারি:
create or alter function dbo.f_GetSharedDataBySession1(@session_id int)
returns table
as
return (
select
d.rn,
d.calculated_number
from dbo.f_GetSharedData(
dbo.fn_GetExperimentYear(@session_id),
dbo.fn_GetExperimentMonth(@session_id)
) as d
)
go
ক্যোয়ারী 1 পরিকল্পনা
অবশ্যই এটি সমান্তরাল নয়, ব্যতীত পরিকল্পনা একই, কারণ ডেটা অ্যাক্সেস সম্পাদনকারী স্কেলার ফাংশনগুলি পুরো পরিকল্পনাটিকে সিরিয়াল করে তোলে ।
সুতরাং আমি বিভিন্ন বিভিন্ন পদ্ধতির চেষ্টা করেছি, যেমন, স্কেলারের ফাংশনগুলির পরিবর্তে সাবকিউরিগুলি ব্যবহার করে:
create or alter function dbo.f_GetSharedDataBySession2(@session_id int)
returns table
as
return (
select
d.rn,
d.calculated_number
from dbo.f_GetSharedData(
(select p.experiment_year from dbo.Params as p where p.session_id = @session_id),
(select p.experiment_month from dbo.Params as p where p.session_id = @session_id)
) as d
)
go
ক্যোয়ারী 2 পরিকল্পনা
বা ব্যবহার cross apply
create or alter function dbo.f_GetSharedDataBySession3(@session_id int)
returns table
as
return (
select
d.rn,
d.calculated_number
from dbo.Params as p
cross apply dbo.f_GetSharedData(
p.experiment_year,
p.experiment_month
) as d
where
p.session_id = @session_id
)
go
ক্যোয়ারী 3 পরিকল্পনা
তবে স্কেলার ফাংশনটি ব্যবহার করে যেমন করা যায় তেমন ভাল হওয়ার জন্য এই কোয়েরিটি লেখার কোনও উপায় আমি খুঁজে পাচ্ছি না।
দু'দিক চিন্তা:
- মূলত আমি যা চাই তা হ'ল কোনওভাবে এসকিউএল সার্ভারকে নির্দিষ্ট মানগুলি প্রাক-গণনা করতে এবং তারপরে ধ্রুবক হিসাবে আরও পাস করার জন্য সক্ষম হওয়া।
- সহায়ক কি হতে পারে যদি আমাদের কিছু মধ্যবর্তী বস্তুগতকরণের ইঙ্গিত থাকে। আমি বেশ কয়েকটি ভেরিয়েন্ট পরীক্ষা করেছি (মাল্টি-স্টেটমেন্ট টিভিএফ বা শীর্ষে সিটি), তবে এখন পর্যন্ত স্কেলার ফাংশনগুলির মতো কোনও পরিকল্পনা তেমন ভাল নয় no
- এসকিউএল সার্ভারের উন্নতি সম্পর্কে আমি জানি 2017 - ফায়ারয়েড: একটি সম্পর্কিত সম্পর্কিত ডেটাবেজে আবশ্যক প্রোগ্রামগুলির অনুকূলকরণ Iআমি নিশ্চিত নই যদিও এটি সাহায্য করবে। যদিও এখানে ভুল প্রমাণিত হয়ে ভাল লাগত।
অতিরিক্ত তথ্য
আমি একটি ফাংশন ব্যবহার করছি (টেবিলগুলি থেকে সরাসরি ডেটা নির্বাচন করার চেয়ে) কারণ অনেকগুলি বিভিন্ন ক্যোয়ারিতে এটি ব্যবহার করা অনেক সহজ, যা সাধারণত @session_id
প্যারামিটার হিসাবে থাকে ।
আমাকে প্রকৃত মৃত্যুদণ্ডের সময় তুলনা করতে বলা হয়েছিল। এই বিশেষ ক্ষেত্রে
- ক্যোয়ারী 0 ~ 500ms এর জন্য চালায়
- ক্যোয়ারী 1 runs 1500ms এর জন্য রান করে
- ক্যোয়ারী 2 ~ 1500ms এর জন্য রান করে
- ক্যোরি 3 2000 ডলারে চালায়।
প্ল্যান # 2 এর সন্ধানের পরিবর্তে একটি সূচক স্ক্যান রয়েছে, যা নেস্টেড লুপগুলিতে পূর্বাভাস দ্বারা ফিল্টার করা হয়। প্ল্যান # 3 এটি খারাপ নয়, তবে আরও বেশি কাজ করে এবং ধীর গতিতে কাজ করে যে পরিকল্পনা # 0।
ধরা যাক dbo.Params
এটি খুব কমই পরিবর্তিত হয়েছে এবং সাধারণত প্রায় 1-200 সারি থাকে, এর চেয়ে বেশি নয়, ধরা যাক 2000 কখনও প্রত্যাশিত। এটি এখন প্রায় 10 টি কলাম এবং আমি প্রায়শই কলাম যুক্ত করার আশা করি না।
প্যারামগুলিতে সারিগুলির সংখ্যা নির্ধারিত নয়, সুতরাং প্রত্যেকের জন্য @session_id
একটি সারি থাকবে। সেখানে কলামগুলির সংখ্যা নির্ধারিত নয়, এটি আমি যে কোনও জায়গা থেকে কল করতে চাই না তার অন্যতম কারণ dbo.f_GetSharedData(@experiment_year int, @experiment_month int)
, তাই আমি অভ্যন্তরীণভাবে এই কোয়েরিতে নতুন কলাম যুক্ত করতে পারি। আমি এতে কোনও মতামত / পরামর্শ শুনে খুশি হব, এমনকি এতে কিছুটা বিধিনিষেধ রয়েছে।