সূচকটি any = কোনও () with দিয়ে ব্যবহৃত হয় না তবে `ইন` দিয়ে ব্যবহৃত হয়`


15

সারণীতে tদুটি সূচক রয়েছে:

create table t (a int, b int);
create type int_pair as (a int, b int);
create index t_row_idx on t (((a,b)::int_pair));
create index t_a_b_idx on t (a,b);

insert into t (a,b)
select i, i
from generate_series(1, 100000) g(i)
;

anyঅপারেটরের সাথে কোনও সূচক ব্যবহার করা হয় না :

explain analyze
select *
from t
where (a,b) = any(array[(1,1),(1,2)])
;
                                            QUERY PLAN                                             
---------------------------------------------------------------------------------------------------
 Seq Scan on t  (cost=0.00..1693.00 rows=1000 width=8) (actual time=0.042..126.789 rows=1 loops=1)
   Filter: (ROW(a, b) = ANY (ARRAY[ROW(1, 1), ROW(1, 2)]))
   Rows Removed by Filter: 99999
 Planning time: 0.122 ms
 Execution time: 126.836 ms

তবে এর মধ্যে একটি inঅপারেটরের সাথে ব্যবহৃত হয় :

explain analyze
select *
from t
where (a,b) in ((1,1),(1,2))
;
                                                    QUERY PLAN                                                    
------------------------------------------------------------------------------------------------------------------
 Index Only Scan using t_a_b_idx on t  (cost=0.29..8.32 rows=1 width=8) (actual time=0.028..0.029 rows=1 loops=1)
   Index Cond: (a = 1)
   Filter: ((b = 1) OR (b = 2))
   Heap Fetches: 1
 Planning time: 0.161 ms
 Execution time: 0.066 ms

এটি রেকর্ড সূচকটি ব্যবহার করে যদি রেকর্ডটি সঠিক ধরণের হয়ে থাকে:

explain analyze
select *
from t
where (a,b)::int_pair = any(array[row(1,1),row(1,2)])
;
                                                  QUERY PLAN                                                  
--------------------------------------------------------------------------------------------------------------
 Index Scan using t_row_idx on t  (cost=0.42..12.87 rows=2 width=8) (actual time=0.106..0.126 rows=1 loops=1)
   Index Cond: (ROW(a, b)::int_pair = ANY (ARRAY[ROW(1, 1), ROW(1, 2)]))
 Planning time: 0.208 ms
 Execution time: 0.203 ms

anyঅপারেটরের জন্য পরিকল্পনাকারী অপারেটরের জন্য নন রেকর্ড সূচকটি ব্যবহার করে না কেন in?


এই আকর্ষণীয় প্রশ্নটি এসও সম্পর্কিত একটি আলোচনা থেকে উঠে এসেছে: stackoverflow.com/a/34601242/939860
এরউইন ব্র্যান্ডসেটেটার

উত্তর:


13

অভ্যন্তরীণভাবে, নির্মাণের পাশাপাশি দুটি পৃথক ফর্ম রয়েছে ।INANY

প্রত্যেকটির একটি, একটি সেট নেওয়া অন্যটির সমতুল্য এবং expr IN (<set>)একই ক্যোয়ারী পরিকল্পনার দিকে নিয়ে যায় expr = ANY(<set>)যা একটি সরল সূচক ব্যবহার করতে পারে। বিবরণ:

ফলস্বরূপ, নিম্নলিখিত দুটি প্রশ্নের সমতুল্য এবং উভয়ই সরল সূচকটি ব্যবহার করতে পারে t_a_b_idx( আপনি যদি সূচিটি ব্যবহার করার জন্য নিজের জিজ্ঞাসাটি পাওয়ার চেষ্টা করছেন তবে এটি সমাধানও হতে পারে ):

EXPLAIN ANALYZE
SELECT *
FROM t
WHERE (a,b) = ANY(VALUES (1,1),(1,2));

বা:

...
WHERE (a,b) IN (VALUES (1,1),(1,2));

উভয়ের জন্য একই:

                                                        QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------
 Nested Loop  (cost=0.33..16.71 rows=1 width=8) (actual time=0.101..0.101 rows=0 loops=1)
   ->  Unique  (cost=0.04..0.05 rows=2 width=8) (actual time=0.068..0.070 rows=2 loops=1)
         ->  Sort  (cost=0.04..0.04 rows=2 width=8) (actual time=0.067..0.068 rows=2 loops=1)
               Sort Key: "*VALUES*".column1, "*VALUES*".column2
               Sort Method: quicksort  Memory: 25kB
               ->  Values Scan on "*VALUES*"  (cost=0.00..0.03 rows=2 width=8) (actual time=0.005..0.005 rows=2 loops=1)
   ->  Index Only Scan using t_plain_idx on t  (cost=0.29..8.32 rows=1 width=8) (actual time=0.009..0.009 rows=0 loops=2)
         Index Cond: ((a = "*VALUES*".column1) AND (b = "*VALUES*".column2))
         Heap Fetches: 0
 Planning time: 4.080 ms
 Execution time: 0.202 ms

তবে পোস্টগ্রিসে কোনও "টেবিল ভেরিয়েবল" না থাকায় এটি সহজে কোনও ফাংশনে স্থানান্তরিত করা যায় না। যা এই বিষয়টিকে শুরু করে এমন সমস্যার দিকে পরিচালিত করে:

এই সমস্যাটির জন্য বিভিন্ন কর্মকাণ্ড রয়েছে। একটি আমি সেখানে যুক্ত বিকল্প বিকল্প হ'ল। কিছু অন্যদের:


প্রত্যেকের দ্বিতীয় ফর্মটি পৃথক: ANYএকটি প্রকৃত অ্যারেIN নেয় , যখন কমা দ্বারা পৃথক করা মানগুলির তালিকা নেয় ।

ইনপুট টাইপ করার জন্য এর বিভিন্ন পরিণতি রয়েছে । আমরা EXPLAINপ্রশ্নের আউটপুটে দেখতে পাচ্ছি , এই ফর্মটি:

WHERE (a,b) = ANY(ARRAY[(1,1),(1,2)]);

শর্টহ্যান্ড হিসাবে দেখা হয়:

ROW(a, b) = ANY (ARRAY[ROW(1, 1), ROW(1, 2)])

এবং প্রকৃত ROW মানগুলি তুলনা করা হয়। যৌগিক ধরণের সূচকটি t_row_idxপ্রযোজ্য তা দেখতে পোস্টগ্র্রেস বর্তমানে যথেষ্ট স্মার্ট নয়। বা এটি উপলব্ধি করে না যে সরল সূচকটিও t_a_b_idxপ্রযোজ্য উচিত।

একটি স্পষ্ট কাস্ট এই স্মার্টগুলির অভাব কাটিয়ে উঠতে সহায়তা করে:

WHERE (a,b)::int_pair = ANY(ARRAY[(1,1),(1,2)]::int_pair[]);

ডান অপারেন্ড ( ::int_pair[]) কাস্টিং optionচ্ছিক ( যদিও পারফরম্যান্সের জন্য এবং অস্পষ্টতা এড়ানোর জন্য পছন্দনীয়)। বাম অপারেণ্ডে একটি সুপরিচিত টাইপ হয়ে গেলে ডান অপারেন্ডটি "বেনামে রেকর্ড" থেকে একটি মিলের ধরণে জোর করা হয়। কেবল তখনই অপারেটরটিকে নির্বিঘ্নভাবে সংজ্ঞায়িত করা হয়। এবং পোস্টগ্রাস অপারেটর এবং বাম অপারেন্ডের উপর ভিত্তি করে প্রযোজ্য সূচকগুলি বেছে নিয়েছে । অনেকগুলি অপারেটর যা একটিকে সংজ্ঞায়িত করে COMMUTATOR, ক্যোয়ারী পরিকল্পনাকারী সূচী প্রকাশটি বাম দিকে আনতে অপারেশনগুলি ফ্লিপ করতে পারে। তবে এটি ANYনির্মাণের সাথে সম্ভব নয় not

সম্পর্কিত:

.. মানগুলি উপাদান হিসাবে নেওয়া হয় এবং পোস্টগ্রিস পৃথক পূর্ণসংখ্যার মানগুলির সাথে তুলনা করতে সক্ষম হয় যেহেতু আমরা EXPLAINআরও একবার আউটপুটে দেখতে পাচ্ছি :

Filter: ((b = 1) OR (b = 2))

অতএব Postgres সন্ধান করেছে যে সহজ সূচক t_a_b_idxব্যবহার করা যেতে পারে।


ফলস্বরূপ, উদাহরণে বিশেষ কেসের জন্য আরও একটি সমাধান হতে পারে : যেহেতু উদাহরণে কাস্টম সংমিশ্রিত ধরণটি int_pairটেবিলের সারি ধরণের সমতুল্য হয় t, তাই আমরা সহজ করতে পারি:

CREATE INDEX t_row_idx2 ON t ((t));

তাহলে এই ক্যোয়ারীটি আরও স্পষ্টত castালাই ছাড়াই সূচি ব্যবহার করবে:

EXPLAIN ANALYZE
SELECT *
FROM   t
WHERE  t = ANY(ARRAY[(1,1),(1,2)]);
                                                      QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on t  (cost=40.59..496.08 rows=1000 width=8) (actual time=0.19
1..0.191 rows=0 loops=1)
   Recheck Cond: (t.* = ANY (ARRAY[ROW(1, 1), ROW(1, 2)]))
   ->  Bitmap Index Scan on t_row_idx2  (cost=0.00..40.34 rows=1000 width=0) (actual time=0.188..0.188 rows=0 loops=1)
         Index Cond: (t.* = ANY (ARRAY[ROW(1, 1), ROW(1, 2)]))
 Planning time: 2.575 ms
 Execution time: 0.267 ms

তবে সাধারণ ব্যবহারের ক্ষেত্রে টেবিল সারিটির অন্তর্নিহিত বিদ্যমান ধরণের ব্যবহার করতে সক্ষম হবে না।


1
একটি সামান্য সংযোজন: একটি সংক্ষিপ্ত IN(...)তালিকা ... OR ...উপরোক্ত ক্ষেত্রে একটি অভিব্যক্তিতে (পরিকল্পনাকারী দ্বারা) অনুবাদ করা যেতে পারে , এটি সাধারণত কেবল অনুবাদ করা হয় ANY('{...}'), যা অ্যারে ব্যবহার করে। সুতরাং, বেশিরভাগ ক্ষেত্রে, INমানগুলির তালিকা সহ এবং ANYএকটি অ্যারে একই জিনিস।
dezso

1
@ ডেজো: বেশিরভাগ সাধারণ ক্ষেত্রে, হ্যাঁ। প্রশ্ন একটি মামলা যেখানে প্রমান IN(...) করতে পারবে না থেকে অনুবাদ করা = ANY('{...}')
এরউইন ব্র্যান্ডসেটেটার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.