অ্যারে_অ্যাগ () অ-সমষ্টিগত এআরএআর () নির্মাতার চেয়ে ধীর কেন?


14

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

SELECT array_agg(x ORDER BY x DESC) FROM foobar;

যাইহোক, একসময় এটি লেখা হয়েছিল,

SELECT ARRAY(SELECT x FROM foobar ORDER BY x DESC);

সুতরাং, আমি এটি কিছু পরীক্ষার ডেটা দিয়ে চেষ্টা করেছি ..

CREATE TEMP TABLE foobar AS
SELECT * FROM generate_series(1,1e7)
  AS t(x);

ফলাফলগুলি অবাক করে দিয়েছিল .. # ওল্ডস্কুলকুলের পথটি ছিল ব্যাপকভাবে: 25% স্পিডআপ। তাছাড়া, এটা সরল ছাড়া আদেশ, একই মন্থরতা দেখিয়েছেন।

# EXPLAIN ANALYZE SELECT ARRAY(SELECT x FROM foobar);
                                                         QUERY PLAN                                                          
-----------------------------------------------------------------------------------------------------------------------------
 Result  (cost=104425.28..104425.29 rows=1 width=0) (actual time=1665.948..1665.949 rows=1 loops=1)
   InitPlan 1 (returns $0)
     ->  Seq Scan on foobar  (cost=0.00..104425.28 rows=6017728 width=32) (actual time=0.032..716.793 rows=10000000 loops=1)
 Planning time: 0.068 ms
 Execution time: 1671.482 ms
(5 rows)

test=# EXPLAIN ANALYZE SELECT array_agg(x) FROM foobar;
                                                        QUERY PLAN                                                         
---------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=119469.60..119469.61 rows=1 width=32) (actual time=2155.154..2155.154 rows=1 loops=1)
   ->  Seq Scan on foobar  (cost=0.00..104425.28 rows=6017728 width=32) (actual time=0.031..717.831 rows=10000000 loops=1)
 Planning time: 0.054 ms
 Execution time: 2174.753 ms
(4 rows)

সুতরাং, এখানে কি চলছে। অ্যারে_অ্যাগ , কেন পরিকল্পনার এসকিউএল ভুডোর তুলনায় একটি অভ্যন্তরীণ ফাংশন এত ধীর?

Gcc দ্বারা সংকলিত x86_64-pc-linux- gnu- এ " পোস্টগ্রাইএসকিউএল 9.5.5 ব্যবহার করে (উবুন্টু 6.2.0-5ubuntu12) 6.2.0 20161005, -৪-বিট"

উত্তর:


17

এআরএআর নির্মাতা সম্পর্কে "পুরাতন স্কুল" বা "পুরানো" কিছুই নেই (এটি ARRAY(SELECT x FROM foobar)হ'ল)। এটি বরাবরের মতো আধুনিক। সাধারণ অ্যারে সমষ্টি জন্য এটি ব্যবহার করুন।

ম্যানুয়াল:

একটি subquery ফলাফল থেকে একটি অ্যারে নির্মাণ করা সম্ভব। এই ফর্মটিতে অ্যারে কনস্ট্রাক্টর মূল শব্দের সাথে রচনা করা হয়েছে যার ARRAYপরে একটি প্রথম বন্ধনীযুক্ত (বন্ধনীযুক্ত নয়) সাবকোয়ারি রয়েছে।

সমষ্টিগত ফাংশনarray_agg() বহুমুখী মধ্যে যে এটি একটি মধ্যে একত্রিত করা যেতে পারে বেশি SELECTবেশি কলাম, একই সম্ভবত আরো aggregations সঙ্গে তালিকা SELECT, এবং নির্বিচারে দলের সাথে যাবে গঠিত GROUP BY। যখন একটি আরআর নির্মাণকারীর কেবলমাত্র SELECTএকটি একক কলাম প্রত্যাবর্তন থেকে কেবল একটি একক অ্যারে প্রদান করতে পারে ।

আমি উত্স কোডটি অধ্যয়ন করি নি, তবে এটি স্পষ্ট বলে মনে হয় যে বহুমুখী সরঞ্জামটি আরও ব্যয়বহুল।

একটি উল্লেখযোগ্য পার্থক্য: এ আরআরএ কনস্ট্রাক্টর {}কোনও সারি যোগ্য না হলে খালি অ্যারে ( ) প্রদান করে। একই জন্য array_agg()ফেরত NULL


6

আমি বিশ্বাস করি যে এরভিনের গৃহীত উত্তরগুলি নিম্নলিখিতগুলির সাথে যুক্ত করা যেতে পারে।

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

উদাহরণস্বরূপ, নিম্নলিখিত কোয়েরি অনুমান করুন:

SELECT ARRAY(SELECT c FROM t ORDER BY id)

আমাদের যদি একটি সূচক থাকে t(id, ...), তবে সূচিটি ক্রমান্বয়ে স্ক্যানের tপরে একটি ক্রম অনুসারে ব্যবহার করা যেতে পারে t.id। অতিরিক্তভাবে, যদি আউটপুট কলামটি অ্যারেতে আবৃত থাকে (এখানে c) সূচকের অংশ হয় (যেমন একটি সূচক উপর একটি সূচি t(id, c)অন্তর্ভুক্ত থাকে বা এতে অন্তর্ভুক্ত সূচক অন্তর্ভুক্ত থাকে t(id) include(c)) তবে এটি এমনকি সূচক-কেবল স্ক্যানও হতে পারে।

এখন, আসুন নিম্নলিখিত হিসাবে সেই প্রশ্নের পুনরায় লেখুন:

SELECT ARRAY_AGG(c ORDER BY id) FROM t

এখন, সমষ্টিটি সূচকটি ব্যবহার করবে না এবং এটি সারিগুলিকে মেমরিতে বাছাই করতে হবে (বা এমনকি বড় ডেটা সেটগুলির জন্য আরও খারাপ, ডিস্কে)। এটি সর্বদা tসংগ্রহ বাছাইয়ের পরে ক্রমিক স্ক্যান হবে

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


2
ভাল যুক্তি. কিন্তু সব সততা, সঙ্গে জিজ্ঞাস্য array_agg()বা অনুরূপ সমষ্টিগত ফাংশন করতে পারেন মতো subquery সাথে এখনও লিভারেজ ইনডেক্স: SELECT ARRAY_AGG(c) FROM (SELECT c FROM t ORDER BY id) sub। প্রতি-সমষ্টিগত ORDER BYধারাটি যা আপনার উদাহরণে সূচক ব্যবহারকে বাধা দেয়। একটি অ্যারে কনস্ট্রাক্টর যখন একই সূচক (বা উভয়ই) ব্যবহার করতে পারে তার চেয়ে দ্রুতarray_agg() হয়। এটা ঠিক বহুমুখী নয়। দেখুন: dba.stackexchange.com/a/213724/3684
এরউইন ব্র্যান্ডস্টেটার

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

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

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