এসকিউএল সার্ভারে সাংখ্যিক পরিসীমা (অন্তর) অনুসন্ধানগুলি অনুকূল করা


18

এই প্রশ্নটি আইপি রেঞ্জ অনুসন্ধানটি অপ্টিমাইজ করার মতো ? তবে এটি এসকিউএল সার্ভার 2000 এ সীমাবদ্ধ।

ধরুন আমার কাছে 10 মিলিয়ন রেঞ্জ অস্থায়ীভাবে সারণিতে কাঠামোগতভাবে সজ্জিত এবং জনবহুল রয়েছে।

CREATE TABLE MyTable
(
Id        INT IDENTITY PRIMARY KEY,
RangeFrom INT NOT NULL,
RangeTo   INT NOT NULL,
CHECK (RangeTo > RangeFrom),
INDEX IX1 (RangeFrom,RangeTo),
INDEX IX2 (RangeTo,RangeFrom)
);

WITH RandomNumbers
     AS (SELECT TOP 10000000 ABS(CRYPT_GEN_RANDOM(4)%100000000) AS Num
         FROM   sys.all_objects o1,
                sys.all_objects o2,
                sys.all_objects o3,
                sys.all_objects o4)
INSERT INTO MyTable
            (RangeFrom,
             RangeTo)
SELECT Num,
       Num + 1 + CRYPT_GEN_RANDOM(1)
FROM   RandomNumbers 

মান সহ সমস্ত ব্যাপ্তি আমার জানা দরকার 50,000,000। আমি নিম্নলিখিত জিজ্ঞাসা চেষ্টা

SELECT *
FROM MyTable
WHERE 50000000 BETWEEN RangeFrom AND RangeTo

এসকিউএল সার্ভার দেখায় যে এখানে 10,951 লজিকাল রিড ছিল এবং 12 টি মিলে পুনরায় পাঠাতে প্রায় 5 মিলিয়ন সারি পড়েছিল।

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

আমি এই পারফরম্যান্স উন্নতি করতে পারেন? সারণীর কোনও পুনর্গঠন বা অতিরিক্ত সূচী ঠিক আছে।


যদি আমি টেবিলের সেট আপটি সঠিকভাবে বুঝতে পারি তবে আপনি প্রতিটি রেঞ্জের "আকার" এ কোনও সীমাবদ্ধতা ছাড়াই আপনার রেঞ্জগুলি গঠনের জন্য এলোমেলোভাবে সংখ্যা বেছে নিচ্ছেন। এবং আপনার তদন্তটি সামগ্রিক পরিসরের ১.১০০ মিটারের মাঝামাঝি জন্য। সেক্ষেত্রে - অভিন্ন এলোমেলো কারণে কোন আপাত ক্লাস্টারিং - আমি জানি না যে কেন নিম্ন বাউন্ডে বা উপরের দিকের একটি সূচক সহায়ক হবে। আপনি কি তা ব্যাখ্যা করতে পারেন?
ডেভিডবাক

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

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

উত্তর:


11

অর্ধ সারণী স্ক্যান করে এমন একটি অবিচ্ছিন্ন সূচকের তুলনায় কলামস্টোর এখানে খুব হেল্পফুল। একটি অবিচ্ছিন্ন কলামস্টোর সূচক বেশিরভাগ সুবিধা সরবরাহ করে তবে একটি ক্লাস্টারযুক্ত কলামস্টোর সূচীতে অর্ডার করা ডেটা evenোকানো আরও ভাল।

DROP TABLE IF EXISTS dbo.MyTableCCI;

CREATE TABLE dbo.MyTableCCI
(
Id        INT PRIMARY KEY,
RangeFrom INT NOT NULL,
RangeTo   INT NOT NULL,
CHECK (RangeTo > RangeFrom),
INDEX CCI CLUSTERED COLUMNSTORE
);

INSERT INTO dbo.MyTableCCI
SELECT TOP (987654321) *
FROM dbo.MyTable
ORDER BY RangeFrom ASC
OPTION (MAXDOP 1);

ডিজাইনের সাহায্যে আমি RangeFromকলামে রাউগ্রুপ নির্মূল করতে পারি যা আমার রাউগ্রুপগুলির অর্ধেকটি সরিয়ে ফেলবে। তবে ডেটা প্রকৃতির কারণে আমি কলামেও রোগ্রুপ বিলোপ পেতে পারি RangeTo:

Table 'MyTableCCI'. Segment reads 1, segment skipped 9.

আরও ভেরিয়েবল ডেটা সহ বৃহত্তর টেবিলগুলির জন্য উভয় কলামে সর্বোত্তম সম্ভাব্য রাউগ্রুপ নির্মূলের গ্যারান্টি রাখতে ডেটা লোড করার বিভিন্ন উপায় রয়েছে। বিশেষত আপনার ডেটাগুলির জন্য, ক্যোয়ারীটি 1 এমএস করে।


হ্যাঁ, 2000 সীমাবদ্ধতা ছাড়াই অবশ্যই বিবেচনা করার জন্য অন্যান্য পদ্ধতির সন্ধান করছে। এমন আওয়াজ না পেটানো হবে।
মার্টিন স্মিথ

9

পল হোয়াইট ইটজিক বেন গানের একটি আকর্ষণীয় নিবন্ধের লিঙ্কযুক্ত অনুরূপ প্রশ্নের উত্তরের দিকে ইঙ্গিত করেছিলেন । এটি "স্ট্যাটিক রিলেশনাল ইন্টারভাল ট্রি" মডেলটির বর্ণনা দেয় যা দক্ষতার সাথে এটি করার অনুমতি দেয়।

সংক্ষেপে এই পদ্ধতির মধ্যে সারিটির অন্তর অন্তরগুলির উপর ভিত্তি করে একটি গণনা করা ("ফর্কনোড") মান সংরক্ষণ করা জড়িত। সীমাটি যে অন্য রেঞ্জকে ছেদ করে এমন সীমাটি অনুসন্ধান করার সময় সর্বাধিক 31 সন্ধানের ক্রিয়াকলাপের সাথে ফলাফলগুলি খুঁজে পেতে এই সম্ভাব্য ফোরকনোড মানগুলির প্রাক্কলকুলেট করা সম্ভব (নীচে 0 থেকে সর্বাধিক স্বাক্ষরিত 32 পর্যন্ত পূর্ণসংখ্যাগুলি সমর্থন করে) বিট ইন্ট)

এর উপর ভিত্তি করে আমি নীচে টেবিলটি পুনর্গঠন করেছি।

CREATE TABLE dbo.MyTable3
(
  Id        INT IDENTITY PRIMARY KEY,
  RangeFrom INT NOT NULL,
  RangeTo   INT NOT NULL,   
  node  AS RangeTo - RangeTo % POWER(2, FLOOR(LOG((RangeFrom - 1) ^ RangeTo, 2))) PERSISTED NOT NULL,
  CHECK (RangeTo > RangeFrom)
);

CREATE INDEX ix1 ON dbo.MyTable3 (node, RangeFrom) INCLUDE (RangeTo);
CREATE INDEX ix2 ON dbo.MyTable3 (node, RangeTo) INCLUDE (RangeFrom);

SET IDENTITY_INSERT MyTable3 ON

INSERT INTO MyTable3
            (Id,
             RangeFrom,
             RangeTo)
SELECT Id,
       RangeFrom,
       RangeTo
FROM   MyTable

SET IDENTITY_INSERT MyTable3 OFF 

এবং তারপরে নীচের ক্যোয়ারীটি ব্যবহার করা হয়েছে (নিবন্ধটি ছেদকারী অন্তরগুলির সন্ধান করছে সুতরাং বিন্দু সহ একটি অন্তর অন্তর সন্ধান করা এটির হ্রাসকারী ঘটনা)

DECLARE @value INT = 50000000;

;WITH N AS
(
SELECT 30 AS Level, 
       CASE WHEN @value > POWER(2,30) THEN POWER(2,30) END AS selected_left_node, 
       CASE WHEN @value < POWER(2,30) THEN POWER(2,30) END AS selected_right_node, 
       (SIGN(@value - POWER(2,30)) * POWER(2,29)) + POWER(2,30)  AS node
UNION ALL
SELECT N.Level-1,   
       CASE WHEN @value > node THEN node END AS selected_left_node,  
       CASE WHEN @value < node THEN node END AS selected_right_node,
       (SIGN(@value - node) * POWER(2,N.Level-2)) + node  AS node
FROM N 
WHERE N.Level > 0
)
SELECT I.id, I.RangeFrom, I.RangeTo
FROM dbo.MyTable3 AS I
  JOIN N AS L
    ON I.node = L.selected_left_node
    AND I.RangeTo >= @value
    AND L.selected_left_node IS NOT NULL
UNION ALL
SELECT I.id, I.RangeFrom, I.RangeTo
FROM dbo.MyTable3 AS I
  JOIN N AS R
    ON I.node = R.selected_right_node
    AND I.RangeFrom <= @value
    AND R.selected_right_node IS NOT NULL
UNION ALL
SELECT I.id, I.RangeFrom, I.RangeTo
FROM dbo.MyTable3 AS I
WHERE node = @value;

1msআইও পরিসংখ্যান সহ সমস্ত পৃষ্ঠাগুলি ক্যাশে থাকা অবস্থায় এটি সাধারণত আমার মেশিনে চালিত হয়।

Table 'MyTable3'. Scan count 24, logical reads 72, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 4, logical reads 374, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

এবং পরিকল্পনা

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

নোট: উত্সটি নোডগুলিতে যোগ দেওয়ার জন্য পুনরাবৃত্ত সিটিইর পরিবর্তে মাল্টিস্টেটমেন্ট টিভিএফ ব্যবহার করে তবে আমার উত্তরটি স্বতঃস্ফূর্তভাবে তৈরি করার স্বার্থে আমি পরবর্তীটির পক্ষে বেছে নিয়েছি। উত্পাদন ব্যবহারের জন্য আমি সম্ভবত টিভিএফ ব্যবহার করব।


9

আমি এন / সিসিআই পদ্ধতির সাথে প্রতিযোগিতামূলক একটি সারি মোড পদ্ধতির সন্ধান করতে সক্ষম হয়েছি তবে আপনাকে আপনার ডেটা সম্পর্কে কিছু জানা দরকার। ধরুন, আপনি একটি কলাম যে পার্থক্য রয়েছে ছিল RangeFromএবং RangeToএবং তোমাদের সাথে সম্মিলিত এটা ইন্ডেক্স RangeFrom:

ALTER TABLE dbo.MyTableWithDiff ADD DiffOfColumns AS RangeTo-RangeFrom;

CREATE INDEX IXDIFF ON dbo.MyTableWithDiff (DiffOfColumns,RangeFrom) INCLUDE (RangeTo);

আপনি যদি এর আলাদা আলাদা মানগুলি জানতেন তবে প্রাসঙ্গিক সমস্ত ডেটা পেতে আপনি একটি রেঞ্জ ফিল্টার সহ DiffOfColumnsপ্রতিটি মানের সন্ধান করতে পারেন । উদাহরণস্বরূপ, যদি আমরা জানি যে = 2 তারপর জন্য কেবল অনুমোদিত মানগুলি 49999998, 49999999 এবং 50000000. পুনরাবৃত্তির স্বতন্ত্র মান সব পেতে ব্যবহার করা যেতে পারে এবং এটি আপনার ডেটা সেট জন্য ভাল কাজ করে তাদের মধ্যে শুধুমাত্র 256 কারণ। নীচের ক্যোয়ারীটি আমার মেশিনে প্রায় 6 এমএস লাগবে:DiffOfColumnsRangeToDiffOfColumnsRangeFromDiffOfColumns

WITH RecursiveCTE
AS
(
    -- Anchor
    SELECT TOP (1)
        DiffOfColumns
    FROM dbo.MyTableWithDiff AS T
    ORDER BY
        T.DiffOfColumns

    UNION ALL

    -- Recursive
    SELECT R.DiffOfColumns
    FROM
    (
        -- Number the rows
        SELECT 
            T.DiffOfColumns,
            rn = ROW_NUMBER() OVER (
                ORDER BY T.DiffOfColumns)
        FROM dbo.MyTableWithDiff AS T
        JOIN RecursiveCTE AS R
            ON R.DiffOfColumns < T.DiffOfColumns
    ) AS R
    WHERE
        -- Only the row that sorts lowest
        R.rn = 1
)
SELECT ca.*
FROM RecursiveCTE rcte
CROSS APPLY (
    SELECT mt.Id, mt.RangeFrom, mt.RangeTo
    FROM dbo.MyTableWithDiff mt
    WHERE mt.DiffOfColumns = rcte.DiffOfColumns
    AND mt.RangeFrom >= 50000000 - rcte.DiffOfColumns AND mt.RangeFrom <= 50000000
) ca
OPTION (MAXRECURSION 0);

প্রতিটি স্বতন্ত্র মানের জন্য সূচকের সন্ধানের পাশাপাশি আপনি স্বাভাবিক পুনরাবৃত্ত অংশটি দেখতে পারেন:

ক্যোয়ারী প্ল্যান 1

এই পদ্ধতির ত্রুটিটি হ'ল ধীরে ধীরে শুরু হতে থাকে যখন এর জন্য অনেকগুলি স্বতন্ত্র মান রয়েছে DiffOfColumns। আসুন একই পরীক্ষা করা যাক, তবে CRYPT_GEN_RANDOM(2)পরিবর্তে ব্যবহার করুন CRYPT_GEN_RANDOM(1)

DROP TABLE IF EXISTS dbo.MyTableBigDiff;

CREATE TABLE dbo.MyTableBigDiff
(
Id        INT IDENTITY PRIMARY KEY,
RangeFrom INT NOT NULL,
RangeTo   INT NOT NULL,
CHECK (RangeTo > RangeFrom)
);

WITH RandomNumbers
     AS (SELECT TOP 10000000 ABS(CRYPT_GEN_RANDOM(4)%100000000) AS Num
         FROM   sys.all_objects o1,
                sys.all_objects o2,
                sys.all_objects o3,
                sys.all_objects o4)
INSERT INTO dbo.MyTableBigDiff
            (RangeFrom,
             RangeTo)
SELECT Num,
       Num + 1 + CRYPT_GEN_RANDOM(2) -- note the 2
FROM   RandomNumbers;


ALTER TABLE dbo.MyTableBigDiff ADD DiffOfColumns AS RangeTo-RangeFrom;

CREATE INDEX IXDIFF ON dbo.MyTableBigDiff (DiffOfColumns,RangeFrom) INCLUDE (RangeTo);

একই ক্যোয়ারী এখন পুনরাবৃত্ত অংশ থেকে 65536 সারি খুঁজে পায় এবং আমার মেশিনে 823 এমপি সিপিইউ নেয়। এখানে PAGELATCH_SH অপেক্ষা এবং অন্যান্য খারাপ জিনিস চলছে। আমি অনন্য মূল্যবোধের সংখ্যা নিয়ন্ত্রণে রাখতে এবং এর মধ্যে বকেটিংয়ের জন্য সামঞ্জস্য করার জন্য পৃথক মানগুলিকে বকেট করে কর্মক্ষমতা উন্নত করতে পারি CROSS APPLY। এই ডেটা সেট করার জন্য আমি 256 বালতি চেষ্টা করব:

ALTER TABLE dbo.MyTableBigDiff ADD DiffOfColumns_bucket256 AS CAST(CEILING((RangeTo-RangeFrom) / 256.) AS INT);

CREATE INDEX [IXDIFF😎] ON dbo.MyTableBigDiff (DiffOfColumns_bucket256, RangeFrom) INCLUDE (RangeTo);

অতিরিক্ত সারি পাওয়া এড়ানোর এক উপায় (এখন আমি সত্য মানের পরিবর্তে একটি বৃত্তাকার মানের সাথে তুলনা করছি) এগুলি ফিল্টার করে RangeTo:

CROSS APPLY (
    SELECT mt.Id, mt.RangeFrom, mt.RangeTo
    FROM dbo.MyTableBigDiff mt
    WHERE mt.DiffOfColumns_bucket256 = rcte.DiffOfColumns_bucket256
    AND mt.RangeFrom >= 50000000 - (256 * rcte.DiffOfColumns_bucket256)
    AND mt.RangeFrom <= 50000000
    AND mt.RangeTo >= 50000000
) ca

সম্পূর্ণ ক্যোয়ারী এখন আমার মেশিনে 6 এমএস নেয়।


8

একটি ব্যাপ্তি উপস্থাপনের একটি বিকল্প উপায় একটি লাইনের পয়েন্ট হিসাবে হবে।

নীচে geometryডেটাটাইপ হিসাবে উপস্থাপিত পরিসীমা সহ সমস্ত তথ্য একটি নতুন টেবিলের মধ্যে স্থানান্তরিত করে ।

CREATE TABLE MyTable2
(
Id INT IDENTITY PRIMARY KEY,
Range GEOMETRY NOT NULL,
RangeFrom AS Range.STPointN(1).STX,
RangeTo   AS Range.STPointN(2).STX,
CHECK (Range.STNumPoints() = 2 AND Range.STPointN(1).STY = 0 AND Range.STPointN(2).STY = 0)
);

SET IDENTITY_INSERT MyTable2 ON

INSERT INTO MyTable2
            (Id,
             Range)
SELECT ID,
       geometry::STLineFromText(CONCAT('LINESTRING(', RangeFrom, ' 0, ', RangeTo, ' 0)'), 0)
FROM   MyTable

SET IDENTITY_INSERT MyTable2 OFF 


CREATE SPATIAL INDEX index_name   
ON MyTable2 ( Range )  
USING GEOMETRY_GRID  
WITH (  
BOUNDING_BOX = ( xmin=0, ymin=0, xmax=110000000, ymax=1 ),  
GRIDS = (HIGH, HIGH, HIGH, HIGH),  
CELLS_PER_OBJECT = 16); 

মানযুক্ত রেঞ্জগুলি সন্ধানের সমতুল্য ক্যোয়ারী 50,000,000নীচে রয়েছে।

SELECT Id,
       RangeFrom,
       RangeTo
FROM   MyTable2
WHERE  Range.STContains(geometry::STPointFromText ('POINT (50000000 0)', 0)) = 1 

10,951মূল ক্যোয়ারী থেকে এইটির জন্য পঠনগুলি উন্নতি দেখায় ।

Table 'MyTable2'. Scan count 0, logical reads 505, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Workfile'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'extended_index_1797581442_384000'. Scan count 4, logical reads 17, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

তবে অতিবাহিত সময়ের নিরিখে মূলটির তুলনায় তাত্পর্যপূর্ণ কোনও উন্নতি নেই । সাধারণত কার্যকর ফলাফলগুলি 250 এমএস বনাম 252 এমএস হয়।

মৃত্যুদন্ড কার্যকর করার পরিকল্পনাটি নীচের মতো আরও জটিল

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

একমাত্র ক্ষেত্রে যেখানে পুনর্লিখনটি নির্ভরযোগ্যভাবে আমার জন্য আরও ভালভাবে সম্পাদন করে তা হ'ল শীতল ক্যাশে।

সুতরাং এই ক্ষেত্রে হতাশাব্যঞ্জক এবং এই পুনর্লিখনের সুপারিশ করা কঠিন তবে নেতিবাচক ফলাফল প্রকাশ করাও কার্যকর হতে পারে।


5

আমাদের নতুন রোবট ওভারলর্ডদের শ্রদ্ধা হিসাবে, আমি সিদ্ধান্ত নিয়েছি যে নতুন-ইশ আর এবং পাইথনের কার্যকারিতা আমাদের এখানে সহায়তা করতে পারে কিনা see উত্তরটি হ'ল কমপক্ষে স্ক্রিপ্টগুলির জন্য যা আমি কাজ করতে পারি এবং সঠিক ফলাফলগুলি ফিরিয়ে আনতে পারি। আরও ভাল জ্ঞান সহ যদি কেউ আসে তবে ভাল, আমাকে স্পঙ্ক করতে নির্দ্বিধায়। আমার হারগুলি যুক্তিসঙ্গত।

এটি করার জন্য, আমি 4 টি কোর এবং 16 গিগাবাইট র‌্যাম সহ একটি ভিএম সেট আপ করেছি, ভেবে এই ~ 200MB ডেটা সেটটি মোকাবেলা করার পক্ষে যথেষ্ট হবে।

বোস্টনের অস্তিত্ব নেই এমন ভাষা দিয়ে শুরু করা যাক!

আর

EXEC sp_execute_external_script 
@language = N'R', 
@script = N'
tweener = 50000000
MO = data.frame(MartinIn)
MartinOut <- subset(MO, RangeFrom <= tweener & RangeTo >= tweener, select = c("Id","RangeFrom","RangeTo"))
', 
@input_data_1_name = N'MartinIn',
@input_data_1 = N'SELECT Id, RangeFrom, RangeTo FROM dbo.MyTable',
@output_data_1_name = N'MartinOut',
@parallel = 1
WITH RESULT SETS ((ID INT, RangeFrom INT, RangeTo INT));

এটি একটি খারাপ সময় ছিল।

Table 'MyTable'. Scan count 1, logical reads 22400

 SQL Server Execution Times:
   CPU time = 3219 ms,  elapsed time = 5349 ms.

মৃত্যুদন্ড পরিকল্পনা প্রশংসনীয় নীরস করা হয়েছে, অথচ আমি কেন মধ্যম অপারেটর আমাদের নাম ডাকতে হয়েছে জানি না।

পাগল

পরবর্তী, crayons সঙ্গে কোডিং!

পাইথন

EXEC sp_execute_external_script 
@language = N'Python', 
@script = N'
import pandas as pd
MO = pd.DataFrame(MartinIn)
tweener = 50000000
MartinOut = MO[(MO.RangeFrom <= tweener) & (MO.RangeTo >= tweener)]
', 
@input_data_1_name = N'MartinIn',
@input_data_1 = N'SELECT Id, RangeFrom, RangeTo FROM dbo.MyTable',
@output_data_1_name = N'MartinOut',
@parallel = 1
WITH RESULT SETS ((ID INT, RangeFrom INT, RangeTo INT));

যখন আপনি ভেবেছিলেন এটি আর এর চেয়ে খারাপ হতে পারে না:

Table 'MyTable'. Scan count 1, logical reads 22400

 SQL Server Execution Times:
   CPU time = 3797 ms,  elapsed time = 10146 ms.

আরেকটি বাজে মুখের বাস্তবায়ন পরিকল্পনা :

পাগল

হুম ও হামার

এখনও অবধি আমি মুগ্ধ হইনি। আমি এই ভিএম মোছার জন্য অপেক্ষা করতে পারি না।


1
আপনি প্যারামিটারগুলিতেও পাস করতে পারেন, যেমন, DECLARE @input INT = 50000001; EXEC dbo.sp_execute_external_script @language = N'R', @script = N'OutputDataSet <- InputDataSet[which(x >= InputDataSet$RangeFrom & x <= InputDataSet$RangeTo) , ]', @parallel = 1, @input_data_1 = N'SELECT Id, RangeFrom, RangeTo FROM dbo.MyTable;', @params = N'@x INT', @x = 50000001 WITH RESULT SETS ( ( Id INT NOT NULL, RangeFrom INT NOT NULL, RangeTo INT NOT NULL ));তবে হ্যাঁ পারফরম্যান্স দুর্দান্ত নয়। এসকিউএল-তে আপনি যে জিনিসগুলি করতে পারবেন না তার জন্য আমি আর ব্যবহার করি, আপনি কিছু অনুমান করতে চান কিনা তা বলুন।
wobi

4

আমি একটি গণিত কলাম ব্যবহার করে একটি দুর্দান্ত ভাল সমাধান পেয়েছি, তবে এটি কেবলমাত্র একক মানের জন্যই ভাল। এটি বলা হচ্ছে, যদি আপনি একটি যাদু মান পেয়ে থাকেন তবে সম্ভবত এটি যথেষ্ট।

আপনার প্রদত্ত নমুনা দিয়ে শুরু করে, তারপরে সারণিটি সংশোধন করুন:

ALTER TABLE dbo.MyTable
    ADD curtis_jackson 
        AS CONVERT(BIT, CASE 
                            WHEN RangeTo >= 50000000
                            AND RangeFrom < 50000000
                            THEN 1 
                            ELSE 0 
                        END);

CREATE INDEX IX1_redo 
    ON dbo.MyTable (curtis_jackson) 
        INCLUDE (RangeFrom, RangeTo);

ক্যোয়ারীটি সহজভাবে হয়:

SELECT *
FROM MyTable
WHERE curtis_jackson = 1;

যা আপনার আরম্ভের ক্যোয়ারির মতো একই ফলাফল দেয়। কার্যকর করার পরিকল্পনা বন্ধ হয়ে যাওয়ার সাথে সাথে এখানে পরিসংখ্যানগুলি (ব্রেভিটির জন্য ছাঁটা):

Table 'MyTable'. Scan count 1, logical reads 3...

SQL Server Execution Times:
  CPU time = 0 ms,  elapsed time = 0 ms.

এবং এখানে ক্যোয়ারী পরিকল্পনাটি রয়েছে :

পাগল


আপনি কি কোনও সূচী দিয়ে গণিত কলাম / ফিল্টারড সূচকের অনুকরণটি কাটিয়ে উঠতে পারবেন না WHERE (50000000 BETWEEN RangeFrom AND RangeTo) INCLUDE (..)?
ypercubeᵀᴹ

3
@ ইপার-পাগলাহাট-কিউব - হ্যাঁ। CREATE INDEX IX1_redo ON dbo.MyTable (curtis_jackson) INCLUDE (RangeFrom, RangeTo) WHERE RangeTo >= 50000000 AND RangeFrom <= 50000000কাজ করবে এবং ক্যোয়ারী SELECT * FROM MyTable WHERE RangeTo >= 50000000 AND RangeFrom <= 50000000;এটি ব্যবহার করে - সুতরাং দরিদ্র কার্টিসের জন্য খুব বেশি প্রয়োজন নেই
মার্টিন স্মিথ

3

আমার সমাধানটি পর্যবেক্ষণের ভিত্তিতে তৈরি করা হয়েছে যে অন্তরটির একটি সর্বাধিক প্রস্থ ডাব্লু রয়েছে । নমুনা ডেটার জন্য এটি এক বাইট বা 256 পূর্ণসংখ্যা। অত: পর একটি প্রদত্ত অনুসন্ধান প্যারামিটার মানের ক্ষেত্রে পি আমরা ক্ষুদ্রতম RangeFrom যে ফলাফল সেট হতে পারে জানেন পি - Cybo । এটি প্রিডিটকে যুক্ত করে

declare @P int = 50000000;
declare @W int = 256;

select
    *
from MyTable
where @P between RangeFrom and RangeTo
and RangeFrom >= (@P - @W);

আসল সেট আপটি দেওয়া হয়েছে এবং আমার মেশিনটিকে জিজ্ঞাসা করেছে (bit৪ বিট উইন্ডোজ 10, 4-কোর হাইপারথ্রেডেড আই 7, 2.8GHz, 16 গিগাবাইট র‌্যাম) 13 টি সারি দেয়। এই ক্যোয়ারীটি (রেঞ্জফ্রোম, রেঞ্জটো) সূচকের সমান্তরাল সূচি ব্যবহার করে। সংশোধিত ক্যোয়ারী একই সূচীতে সমান্তরাল সূচক অনুসন্ধানও সম্পাদন করে।

মূল এবং সংশোধিত প্রশ্নের জন্য পরিমাপগুলি হ'ল

                          Original  Revised
                          --------  -------
Stats IO Scan count              9        6
Stats IO logical reads       11547        6

Estimated number of rows   1643170  1216080
Number of rows read        5109666       29
QueryTimeStats CPU             344        2
QueryTimeStats Elapsed          53        0

মূল ক্যোয়ারির জন্য পঠিত সারিগুলির সংখ্যা @ পি এর চেয়ে কম বা সমান যে সারিগুলির সমান। ক্যোয়ারী অপ্টিমাইজার (কিউ) এর বিকল্প নেই তবে সেগুলি পড়ুন কারণ এটি আগে থেকেই নির্ধারণ করতে পারে না যে এই সারিগুলি যদি প্রাকটিকাকে সন্তুষ্ট করে তবে। (রেঞ্জফ্রোম, রেঞ্জটো) মাল্টি কলাম-ইনডেক্স সূচিগুলি যে রেঞ্জের সাথে মেলে না তা মুছে ফেলতে কার্যকর নয় কারণ প্রথম সূচক কী এবং দ্বিতীয়টি প্রয়োগ করা যেতে পারে between উদাহরণস্বরূপ, প্রথম সারিতে একটি ছোট ব্যবধান থাকতে পারে এবং এটি অপসারণ করা যেতে পারে যেখানে দ্বিতীয় সারিতে বড় ব্যবধান রয়েছে এবং ফিরে আসে, বা বিপরীতে।

একটি ব্যর্থ প্রয়াসে আমি চেক সীমাবদ্ধতার মাধ্যমে সেই নিশ্চয়তা দেওয়ার চেষ্টা করেছি:

alter table MyTable with check
add constraint CK_MyTable_Interval
check
(
    RangeTo <= RangeFrom + 256
);

এটি কোন পার্থক্য তৈরি।

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

মিরর যুক্তি RangeTo উপরের সীমা পি + + ডব্লিউ । তবে এটি কার্যকর নয়, কারণ রেঞ্জফ্রম এবং রেঞ্জটো এর মধ্যে কোনও সম্পর্ক নেই যা মাল্টি-কলাম-ইনডেক্সের অনুবর্তী কলামটি সারিগুলি সরিয়ে দিতে দেয়। সুতরাং কোয়েরিতে এই ধারাটি যুক্ত করে কোনও লাভ নেই।

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

এই উত্তরে বাইরের ত্রুটিগুলির যে কোনও কারণ থাকতে পারে তার জন্য আমি ক্ষমাপ্রার্থী।

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