দক্ষ পরিসীমা সামগ্রিক প্রশ্নের জন্য ডেটাবেস?


11

সরলীকৃত উদাহরণ হিসাবে, ধরুন আমার কাছে এই জাতীয় টেবিল রয়েছে:

seq | value
----+------
102 | 11954
211 | 43292
278 | 19222
499 |  3843

সারণীতে কয়েক মিলিয়ন মিলিয়ন রেকর্ড থাকতে পারে এবং আমার প্রায়শই এই জাতীয় প্রশ্নগুলি করা দরকার:

SELECT sum(value) WHERE seq > $a and seq < $b

এমনকি যদি seqসূচিযুক্ত হয়, তবে একটি সাধারণ ডাটাবেস বাস্তবায়ন প্রতিটি সারির মধ্য দিয়ে লুপ করবে সর্বোত্তম ক্ষেত্রে যোগফলটি গণনা করতে পারে O(n), যেখানে nপরিসরের আকার।

কোয়েরি অনুসারে এমন কোনও ডাটাবেস রয়েছে যা দক্ষতার সাথে এটি করতে পারে O(log(n))?

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

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

পার্শ্ব দ্রষ্টব্য: এটি কেবলমাত্র পরিশিষ্টের টেবিল নয়, সুতরাং সংযোজন যোগফল রাখার মতো সমাধান এই ক্ষেত্রে কার্যকর হবে না।


এটি কলাম-সংগঠিত ডাটাবেসের জন্য সাধারণ ব্যবহারের কেস, যার মধ্যে অনেকগুলি রয়েছে
মোস্তাকাসিও

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

উত্তর:


8

এসকিউএল সার্ভার কলাম স্টোর সূচী ব্যবহার করে

ভাল, ঠিক আছে, কেবল একটি - একটি ক্লাস্টার্ড সিএস সূচক।

আপনি যে হার্ডওয়্যারটি আমি এটি করেছিলাম সে সম্পর্কে যদি আপনি পড়তে চান তবে এখানে যান । সম্পূর্ণ প্রকাশ, আমি যে ব্লগ পোস্টটি লিখেছিলাম সেটির ওয়েবসাইটে আমি কাজ করি।

পরীক্ষায়!

একটি দুর্দান্ত বড় টেবিল তৈরি করতে এখানে কিছু জেনেরিক কোড রয়েছে। ইভান হিসাবে একই সতর্কতা, এটি তৈরি এবং সূচী করতে কিছু সময় নিতে পারে।

USE tempdb

CREATE TABLE t1 (Id INT NOT NULL, Amount INT NOT NULL)

;WITH T (N)
AS ( SELECT X.N
     FROM ( 
      VALUES (NULL), (NULL), (NULL),
             (NULL), (NULL), (NULL),
             (NULL), (NULL), (NULL), 
             (NULL) ) AS X (N) 
           ), NUMS (N) AS ( 
            SELECT TOP ( 710000000 ) 
                    ROW_NUMBER() OVER ( ORDER BY ( SELECT NULL )) AS N
            FROM   T AS T1, T AS T2, T AS T3, 
                   T AS T4, T AS T5, T AS T6, 
                   T AS T7, T AS T8, T AS T9, 
                   T AS T10 )
INSERT dbo.t1 WITH ( TABLOCK ) (
    Id, Amount )
SELECT NUMS.N % 999 AS Id, NUMS.N % 9999 AS Amount
FROM   NUMS;

--(705032704 row(s) affected) --Aw, close enough

ওয়েল, ইভান সরলীকরণের জন্য ধিক্কার জানাই, কিন্তু আমি স্বপ্ন করেছি যে আগে।

সূচী সংজ্ঞা এখানে। লা এবং ডি এবং দাহ।

CREATE CLUSTERED COLUMNSTORE INDEX CX_WOAHMAMA ON dbo.t1

একটি গণনা দেখে, প্রতিটি আইডির একটি সুন্দর এমনকি বিতরণ থাকে:

SELECT t.Id, COUNT(*) AS [Records]
FROM dbo.t1 AS t
GROUP BY t.Id
ORDER BY t.Id

ফলাফল:

Id  Records
0   5005005
1   5005006
2   5005006
3   5005006
4   5005006
5   5005006

...

994 5005005
995 5005005
996 5005005
997 5005005
998 5005005

প্রতিটি আইডিতে ~ 5,005,005 সারি রয়েছে, আমরা আপনাকে একটি 10 ​​মিলিয়ন সারি যোগফল পেতে আইডিগুলির একটি দুর্দান্ত ছোট পরিসরের দিকে নজর দিতে পারি।

SELECT COUNT(*) AS [Records], SUM(t.Amount) AS [Total]
FROM   dbo.t1 AS t
WHERE  t.Id > 0
       AND t.Id < 3;

ফলাফল:

Records     Total
10010012    50015062308

ক্যোয়ারী প্রোফাইল:

Table 't1'. Scan count 6, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 2560758, lob physical reads 0, lob read-ahead reads 0.
Table 't1'. Segment reads 4773, segment skipped 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.

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

মজা করার জন্য, একটি বৃহত্তর সমষ্টি:

SELECT COUNT(*) AS [Records], SUM(CONVERT(BIGINT, t.Amount)) AS [Total]
FROM   dbo.t1 AS t
WHERE  t.Id > 0
       AND t.Id < 101;

ফলাফল:

Records     Total
500500505   2501989114575

ক্যোয়ারী প্রোফাইল:

Table 't1'. Scan count 6, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 2560758, lob physical reads 0, lob read-ahead reads 0.
Table 't1'. Segment reads 4773, segment skipped 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.

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

আশাকরি এটা সাহায্য করবে!



2

একটি ব্রিন সূচক সহ পোস্টগ্রিজ এসকিউএল with

সিক ইনডেক্স করা থাকলেও, একটি সাধারণ ডাটাবেস বাস্তবায়ন প্রতিটি সারির মধ্য দিয়ে লুপ করবে সর্বোত্তম ক্ষেত্রে ও (এন) এর যোগফল গণনা করতে, যেখানে এন ব্যাপ্তির আকার।

এটা সত্যি না. কমপক্ষে, কোনও শালীন ডাটাবেস এটি করবে না। PostgreSQL এই ধরণের টেবিলগুলিতে BRIN ইনডেক্স তৈরি করতে সহায়তা করে। ব্রিন সূচকগুলি অতি ছোট এবং এগুলি বড় টেবিলেও মেষতে ফিট করতে পারে। কয়েক লক্ষ লক্ষ সারি কিছুই নয়।

আপনি যেমন অর্ডার করেছেন ঠিক তেমন এখানে 300 মিলিয়ন সারি সংজ্ঞায়িত করা হয়েছে। সতর্কতা এটিকে তৈরি করতে দীর্ঘ সময় নিতে পারে (সময়: 336057.807 এমএস + 95121.809 এমএস সূচকের জন্য)।

CREATE TABLE foo
AS
  SELECT seq::int, trunc(random()*100000)::int AS v
  FROM generate_series(1,3e8) AS gs(seq);

CREATE INDEX ON foo USING BRIN (seq);

ANALYZE foo;

এবং এখন...

EXPLAIN ANALYZE SELECT sum(v) FROM foo WHERE seq BETWEEN 424242 AND 6313376;
                                                                QUERY PLAN                                                                 
-------------------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=1486163.53..1486163.54 rows=1 width=4) (actual time=1493.888..1493.888 rows=1 loops=1)
   ->  Bitmap Heap Scan on foo  (cost=58718.12..1471876.19 rows=5714938 width=4) (actual time=12.565..1035.153 rows=5889135 loops=1)
         Recheck Cond: ((seq >= 424242) AND (seq <= 6313376))
         Rows Removed by Index Recheck: 41105
         Heap Blocks: lossy=26240
         ->  Bitmap Index Scan on foo_seq_idx  (cost=0.00..57289.38 rows=5714938 width=0) (actual time=10.378..10.378 rows=262400 loops=1)
               Index Cond: ((seq >= 424242) AND (seq <= 6313376))
 Planning time: 0.125 ms
 Execution time: 1493.948 ms
(9 rows)

প্রদত্ত ব্যাপ্তিতে 5,889,135 টি সারিতে মোট / সমষ্টিতে 1.4 সেকেন্ড।

টেবিলটি 10 ​​জিবি হওয়া সত্ত্বেও, ব্রিন সূচক 304 কেবি হয়।

আরও দ্রুত

যদি এটি এখনও পর্যাপ্ত দ্রুত না হয় তবে আপনি 100 কে সারি করে সমষ্টিগুলি ক্যাশে করতে পারেন।

CREATE MATERIALIZED VIEW cache_foo
AS
  SELECT seq/1e5::int AS grp, sum(v)
  FROM foo GROUP BY seq/1e5::int
  ORDER BY 1;

এখন আপনার কেবল 2(1e5-1)300 মিলিয়ন বা যাই হোক না কেন কেবল ব্রিন এবং সামগ্রিক সারি ব্যবহার করা দরকার ।

হার্ডওয়্যারের

লেনোভো x230, i5-3230M, 16 জিবি র‌্যাম, 1 টিবি স্যামসাং 840 এসএসডি D


ধন্যবাদ, আমি পড়ব এবং ব্রিন সূচকগুলি নিয়ে আরও পরীক্ষা করব। এটি এখন পর্যন্ত সেরা বিকল্পের মতো দেখাচ্ছে।
রাল্ফ

3
দুর্দান্ত পরামর্শ, উভয়ই (বিআরআইএন সূচক এবং উপাদানযুক্ত দর্শন)। তবে ক্যারি, এমনকি ব্রিন সূচকের সাথে এখনও ও (এন) রয়েছে। দয়া করে সম্পাদনা করুন এবং অন্যথায় দাবি করবেন না। প্রকৃত দৃশ্য O(n)সম্ভবত চেয়ে ভাল হতে পারে O(sqrt(n))। বস্তুগতকরণে আপনি কীভাবে অন্তরগুলি সংজ্ঞায়িত করবেন তার উপর নির্ভর করে।
ypercubeᵀᴹ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.