আপনি তুলনা করতে পারেন কয়েকটি পদ্ধতি এখানে। প্রথমে কিছু ডামি ডেটা সহ একটি টেবিল সেট আপ করা যাক। আমি এটিকে sys.all_collines থেকে একগুচ্ছ এলোমেলো ডেটা দিয়ে পপুলেট করছি। ওয়েল, এটি এলোমেলো এক ধরণের - আমি নিশ্চিত করছি যে তারিখগুলি সুসংগত (যা উত্তরগুলির জন্য কেবলমাত্র গুরুত্বপূর্ণ)।
CREATE TABLE dbo.Hits(Day SMALLDATETIME, CustomerID INT);
CREATE CLUSTERED INDEX x ON dbo.Hits([Day]);
INSERT dbo.Hits SELECT TOP (5000) DATEADD(DAY, r, '20120501'),
COALESCE(ASCII(SUBSTRING(name, s, 1)), 86)
FROM (SELECT name, r = ROW_NUMBER() OVER (ORDER BY name)/10,
s = CONVERT(INT, RIGHT(CONVERT(VARCHAR(20), [object_id]), 1))
FROM sys.all_columns) AS x;
SELECT
Earliest_Day = MIN([Day]),
Latest_Day = MAX([Day]),
Unique_Days = DATEDIFF(DAY, MIN([Day]), MAX([Day])) + 1,
Total_Rows = COUNT(*)
FROM dbo.Hits;
ফলাফল:
Earliest_Day Latest_Day Unique_Days Total_Days
------------------- ------------------- ----------- ----------
2012-05-01 00:00:00 2013-09-13 00:00:00 501 5000
ডেটা দেখতে (5000 সারি) এর মতো দেখায় - তবে সংস্করণ এবং বিল্ড # এর উপর নির্ভর করে আপনার সিস্টেমে কিছুটা আলাদা দেখাবে
Day CustomerID
------------------- ---
2012-05-01 00:00:00 95
2012-05-01 00:00:00 97
2012-05-01 00:00:00 97
2012-05-01 00:00:00 117
2012-05-01 00:00:00 100
...
2012-05-02 00:00:00 110
2012-05-02 00:00:00 110
2012-05-02 00:00:00 95
...
এবং চলমান মোট ফলাফলের মতো দেখতে হবে (501 সারি):
Day c rt
------------------- -- --
2012-05-01 00:00:00 6 6
2012-05-02 00:00:00 5 11
2012-05-03 00:00:00 4 15
2012-05-04 00:00:00 7 22
2012-05-05 00:00:00 6 28
...
সুতরাং যে পদ্ধতিগুলির সাথে আমি তুলনা করতে চলেছি সেগুলি হ'ল:
- "স্ব-যোগদান" - সেট-ভিত্তিক পিউরিস্ট পদ্ধতির
- "তারিখগুলির সাথে পুনরাবৃত্তির সিটিই" - এটি সংবিধানের তারিখগুলিতে নির্ভর করে (কোনও ফাঁক নেই)
- "সারি_সংখ্যার সাথে পুনরাবৃত্ত সিটিই" - উপরের মত তবে ধীরে ধীরে, ROW_NUMBER এ ভরসা করে
- "টেম্প টেবিল সহ পুনরাবৃত্ত সিটিই" - পরামর্শ হিসাবে মাইকের উত্তর থেকে চুরি হয়েছে
- "কৌতূহলী আপডেট" যা অসমর্থিত এবং সংজ্ঞায়িত আচরণের প্রতিশ্রুতি দেয় না তা বেশ জনপ্রিয় বলে মনে হয়
- "কার্সার"
- এসকিউএল সার্ভার 2012 নতুন উইন্ডোটিং কার্যকারিতা ব্যবহার করে
স্ব-যোগ
লোকেরা আপনাকে কর্সার থেকে দূরে থাকার জন্য সতর্ক করার সময় এইভাবেই আপনাকে এটি করতে বলবে, কারণ "সেট ভিত্তিক সর্বদা দ্রুত হয়।" কিছু সাম্প্রতিক পরীক্ষায় আমি খুঁজে পেয়েছি যে কার্সার এই সমাধানটিকে দ্রুত চালায়।
;WITH g AS
(
SELECT [Day], c = COUNT(DISTINCT CustomerID)
FROM dbo.Hits
GROUP BY [Day]
)
SELECT g.[Day], g.c, rt = SUM(g2.c)
FROM g INNER JOIN g AS g2
ON g.[Day] >= g2.[Day]
GROUP BY g.[Day], g.c
ORDER BY g.[Day];
তারিখের সাথে পুনরাবৃত্ত cte
অনুস্মারক - এটি সংশ্লেষের তারিখগুলিতে (কোনও ফাঁক নেই) পুনরাবৃত্তির 10000 স্তর পর্যন্ত নির্ভর করে এবং আপনি যে সীমাটি আগ্রহী তা শুরু করার তারিখটি জানেন (অ্যাঙ্কর সেট করতে)। আপনি অবশ্যই একটি সাবকিউরিটি ব্যবহার করে গতিময়ভাবে অ্যাঙ্কর সেট করতে পারেন, তবে আমি জিনিসগুলি সহজ রাখতে চেয়েছিলাম।
;WITH g AS
(
SELECT [Day], c = COUNT(DISTINCT CustomerID)
FROM dbo.Hits
GROUP BY [Day]
), x AS
(
SELECT [Day], c, rt = c
FROM g
WHERE [Day] = '20120501'
UNION ALL
SELECT g.[Day], g.c, x.rt + g.c
FROM x INNER JOIN g
ON g.[Day] = DATEADD(DAY, 1, x.[Day])
)
SELECT [Day], c, rt
FROM x
ORDER BY [Day]
OPTION (MAXRECURSION 10000);
সারি_সংখ্যার সাথে পুনরাবৃত্ত সিটি
সারি_সংখ্যার গণনা এখানে কিছুটা ব্যয়বহুল। আবার এটি সর্বোচ্চ স্তরকে 10000 পুনরাবৃত্তি সমর্থন করে, তবে আপনাকে অ্যাঙ্কর বরাদ্দ করার দরকার নেই।
;WITH g AS
(
SELECT [Day], rn = ROW_NUMBER() OVER (ORDER BY DAY),
c = COUNT(DISTINCT CustomerID)
FROM dbo.Hits
GROUP BY [Day]
), x AS
(
SELECT [Day], rn, c, rt = c
FROM g
WHERE rn = 1
UNION ALL
SELECT g.[Day], g.rn, g.c, x.rt + g.c
FROM x INNER JOIN g
ON g.rn = x.rn + 1
)
SELECT [Day], c, rt
FROM x
ORDER BY [Day]
OPTION (MAXRECURSION 10000);
টেম্প টেবিল সহ পুনরাবৃত্ত cte
মাইকের উত্তর থেকে চুরি করা, পরামর্শ হিসাবে এটি পরীক্ষাগুলিতে অন্তর্ভুক্ত করার জন্য।
CREATE TABLE #Hits
(
rn INT PRIMARY KEY,
c INT,
[Day] SMALLDATETIME
);
INSERT INTO #Hits (rn, c, Day)
SELECT ROW_NUMBER() OVER (ORDER BY DAY),
COUNT(DISTINCT CustomerID),
[Day]
FROM dbo.Hits
GROUP BY [Day];
WITH x AS
(
SELECT [Day], rn, c, rt = c
FROM #Hits as c
WHERE rn = 1
UNION ALL
SELECT g.[Day], g.rn, g.c, x.rt + g.c
FROM x INNER JOIN #Hits as g
ON g.rn = x.rn + 1
)
SELECT [Day], c, rt
FROM x
ORDER BY [Day]
OPTION (MAXRECURSION 10000);
DROP TABLE #Hits;
উদ্দীপনা আপডেট
আবার আমি কেবল এটি সম্পূর্ণতার জন্য অন্তর্ভুক্ত করছি; আমি ব্যক্তিগতভাবে এই সমাধানটির উপর নির্ভর করব না, যেহেতু আমি অন্য উত্তরে উল্লেখ করেছি, এই পদ্ধতিটি মোটেই কাজ করার গ্যারান্টিযুক্ত নয় এবং এটি এসকিউএল সার্ভারের ভবিষ্যতের সংস্করণে পুরোপুরি ভেঙে যেতে পারে। (আমি সূচক পছন্দের জন্য একটি ইঙ্গিত ব্যবহার করে এসকিউএল সার্ভারকে আমার যে আদেশটি চাই তা মানতে বাধ্য করার জন্য যথাসাধ্য চেষ্টা করছি।)
CREATE TABLE #x([Day] SMALLDATETIME, c INT, rt INT);
CREATE UNIQUE CLUSTERED INDEX x ON #x([Day]);
INSERT #x([Day], c)
SELECT [Day], c = COUNT(DISTINCT CustomerID)
FROM dbo.Hits
GROUP BY [Day]
ORDER BY [Day];
DECLARE @rt1 INT;
SET @rt1 = 0;
UPDATE #x
SET @rt1 = rt = @rt1 + c
FROM #x WITH (INDEX = x);
SELECT [Day], c, rt FROM #x ORDER BY [Day];
DROP TABLE #x;
কার্সার
"সাবধান, এখানে কার্সার রয়েছে! কার্সাররা মন্দ! আপনার যেকোন মূল্যে কার্সার এড়ানো উচিত!" না, এটি আমি কথা বলছি না, এটি কেবল প্রচুর শুনতে পাওয়া যায় hear জনপ্রিয় মতামতের বিপরীতে, কিছু ক্ষেত্রে রয়েছে যেখানে কার্সারগুলি উপযুক্ত।
CREATE TABLE #x2([Day] SMALLDATETIME, c INT, rt INT);
CREATE UNIQUE CLUSTERED INDEX x ON #x2([Day]);
INSERT #x2([Day], c)
SELECT [Day], COUNT(DISTINCT CustomerID)
FROM dbo.Hits
GROUP BY [Day]
ORDER BY [Day];
DECLARE @rt2 INT, @d SMALLDATETIME, @c INT;
SET @rt2 = 0;
DECLARE c CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR SELECT [Day], c FROM #x2 ORDER BY [Day];
OPEN c;
FETCH NEXT FROM c INTO @d, @c;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @rt2 = @rt2 + @c;
UPDATE #x2 SET rt = @rt2 WHERE [Day] = @d;
FETCH NEXT FROM c INTO @d, @c;
END
SELECT [Day], c, rt FROM #x2 ORDER BY [Day];
DROP TABLE #x2;
এসকিউএল সার্ভার 2012
আপনি যদি এসকিউএল সার্ভারের অতি সাম্প্রতিক সংস্করণে থাকেন তবে উইন্ডোং কার্যকারিতা থেকে বর্ধিতকরণগুলি স্ব-যোগদানের তাত্পর্যপূর্ণ ব্যয় ছাড়াই সহজেই চলমান মোট গণনা করতে দেয় (এসইউএমটি একটি পাসে গণনা করা হয়), সিটিইর জটিলতা (প্রয়োজনীয়তা সহ) আরও ভাল পারফরম্যান্স সিটিই) এর জন্য স্বতন্ত্র সারিগুলির), অসমর্থিত বিশিষ্ট আপডেট এবং নিষিদ্ধ কার্সার। ব্যবহার RANGE
এবং ROWS
, বা কিছু উল্লেখ না করার মধ্যে পার্থক্য সম্পর্কে কেবল সতর্ক থাকুন - কেবল ROWS
একটি অন ডিস্ক স্পুল এড়িয়ে চলে, যা অন্যথায় পারফরম্যান্সকে উল্লেখযোগ্যভাবে বাধা দেয়।
;WITH g AS
(
SELECT [Day], c = COUNT(DISTINCT CustomerID)
FROM dbo.Hits
GROUP BY [Day]
)
SELECT g.[Day], c,
rt = SUM(c) OVER (ORDER BY [Day] ROWS UNBOUNDED PRECEDING)
FROM g
ORDER BY g.[Day];
পারফরম্যান্স তুলনা
আমি প্রতিটি পন্থা গ্রহণ করেছি এবং নিম্নলিখিতটি ব্যবহার করে এটি একটি ব্যাচ জড়িয়েছি:
SELECT SYSUTCDATETIME();
GO
DBCC DROPCLEANBUFFERS;DBCC FREEPROCCACHE;
-- query here
GO 10
SELECT SYSUTCDATETIME();
মিলিসেকেন্ডে মোট সময়কালের ফলাফল এখানে রয়েছে (মনে রাখবেন এটিতে প্রতিবারের মতো ডিবিসিসি কমান্ডও অন্তর্ভুক্ত রয়েছে):
method run 1 run 2
----------------------------- -------- --------
self-join 1296 ms 1357 ms -- "supported" non-SQL 2012 winner
recursive cte with dates 1655 ms 1516 ms
recursive cte with row_number 19747 ms 19630 ms
recursive cte with #temp table 1624 ms 1329 ms
quirky update 880 ms 1030 ms -- non-SQL 2012 winner
cursor 1962 ms 1850 ms
SQL Server 2012 847 ms 917 ms -- winner if SQL 2012 available
আর আমি এটি আবার ডিবিসিসির আদেশ ছাড়াই করেছি:
method run 1 run 2
----------------------------- -------- --------
self-join 1272 ms 1309 ms -- "supported" non-SQL 2012 winner
recursive cte with dates 1247 ms 1593 ms
recursive cte with row_number 18646 ms 18803 ms
recursive cte with #temp table 1340 ms 1564 ms
quirky update 1024 ms 1116 ms -- non-SQL 2012 winner
cursor 1969 ms 1835 ms
SQL Server 2012 600 ms 569 ms -- winner if SQL 2012 available
কেবলমাত্র একটি কাঁচা পুনরাবৃত্তি পরিমাপ করে ডিবিসিসি এবং লুপ উভয়কেই সরিয়ে ফেলা হচ্ছে:
method run 1 run 2
----------------------------- -------- --------
self-join 313 ms 242 ms
recursive cte with dates 217 ms 217 ms
recursive cte with row_number 2114 ms 1976 ms
recursive cte with #temp table 83 ms 116 ms -- "supported" non-SQL 2012 winner
quirky update 86 ms 85 ms -- non-SQL 2012 winner
cursor 1060 ms 983 ms
SQL Server 2012 68 ms 40 ms -- winner if SQL 2012 available
অবশেষে, আমি উত্স টেবিলের মধ্যে সারি গণনাটি 10 দ্বারা গুণিত করেছি (শীর্ষে 50000 এ পরিবর্তন এবং ক্রস যোগ হিসাবে অন্য সারণী যুক্ত করা)। এর ফলাফল, কোনও একক পুনরাবৃত্তি কোনও ডিবিসিসি আদেশ ছাড়াই (কেবল সময়ের স্বার্থে):
method run 1 run 2
----------------------------- -------- --------
self-join 2401 ms 2520 ms
recursive cte with dates 442 ms 473 ms
recursive cte with row_number 144548 ms 147716 ms
recursive cte with #temp table 245 ms 236 ms -- "supported" non-SQL 2012 winner
quirky update 150 ms 148 ms -- non-SQL 2012 winner
cursor 1453 ms 1395 ms
SQL Server 2012 131 ms 133 ms -- winner
আমি কেবল সময়কাল পরিমাপ করেছি - আমি পাঠকদের কাছে এই ডেটাগুলিতে এই পদ্ধতির তুলনা করার জন্য অনুশীলন হিসাবে ছেড়ে দেব, অন্য গুরুত্বপূর্ণ মেট্রিকগুলির সাথে তুলনা করা যা গুরুত্বপূর্ণ (বা তাদের স্কিমা / ডেটার সাথে পৃথক হতে পারে)। এই উত্তর থেকে কোনও সিদ্ধান্ত নেওয়ার আগে, এটি আপনার ডেটা এবং আপনার স্কিমার বিরুদ্ধে এটি পরীক্ষা করা আপনার হাতে ... সারি সংখ্যা আরও বাড়ার সাথে সাথে এই ফলাফলগুলি অবশ্যই পরিবর্তন হবে।
ডেমো
আমি একটি স্ক্যালফিল্ড যুক্ত করেছি । ফলাফল:
উপসংহার
আমার পরীক্ষায়, পছন্দটি হ'ল:
- এসকিউএল সার্ভার 2012 পদ্ধতি, যদি আমার এসকিউএল সার্ভার 2012 উপলব্ধ থাকে।
- যদি এসকিউএল সার্ভার 2012 উপলভ্য না হয় এবং আমার তারিখগুলি সুসংগত হয় তবে আমি তারিখের পদ্ধতি সহ পুনরাবৃত্ত cte সাথে যেতে পারি।
- যদি না ১ বা ২ প্রযোজ্য হয় তবে আমি আচরণটি নথিভুক্ত ও গ্যারান্টিযুক্ত হওয়ার কারণে পারফরম্যান্সটি কাছাকাছি থাকা সত্ত্বেও উদ্দীপক আপডেটের সাথে স্ব-যোগদানের সাথে যাব। আমি ভবিষ্যতের সামঞ্জস্যতা সম্পর্কে কম চিন্তিত কারণ আশা করি যদি উদ্বেগজনক আপডেটটি ভেঙে যায় তবে আমি ইতিমধ্যে আমার সমস্ত কোডকে ১: :-) রূপান্তর করার পরে এটি হবে will
তবে আবার, আপনার এটি আপনার স্কিমা এবং ডেটার বিরুদ্ধে পরীক্ষা করা উচিত। যেহেতু এটি তুলনামূলকভাবে নিম্ন সারি গণনার সাথে একটি স্বীকৃত পরীক্ষা ছিল, এটি বায়ুতেও খুব দূরে থাকতে পারে। আমি বিভিন্ন স্কিমা এবং সারি গণনা সহ অন্যান্য পরীক্ষা করেছি এবং পারফরম্যান্স হিউরিস্টিকসটি একেবারেই আলাদা ছিল ... এজন্য আমি আপনার মূল প্রশ্নটিতে অনেকগুলি ফলো-আপ প্রশ্ন জিজ্ঞাসা করেছি।
হালনাগাদ
আমি এখানে এই সম্পর্কে আরও ব্লগ করেছি:
মোট রান করার জন্য সেরা পন্থা - এসকিউএল সার্ভার ২০১২-এর জন্য আপডেট
Day
একটি কী এবং মানগুলি কি সামঞ্জস্যপূর্ণ?