স্থানিক সূচকগুলি "সীমা দ্বারা - সীমাবদ্ধ করে" কোয়েরিতে সহায়তা করতে পারে


29

এই প্রশ্নটি জিজ্ঞাসা করা, বিশেষত পোস্টগ্রাসের জন্য, কারণ এতে আর-ট্রি / স্পেসিয়াল ইনডেক্সের ভাল সংযোগ রয়েছে।

আমাদের শব্দের একটি গাছের কাঠামো (নেস্টেট সেট মডেল) এবং তাদের ফ্রিকোয়েন্সি সহ নীচের সারণি রয়েছে:

lexikon
-------
_id   integer  PRIMARY KEY
word  text
frequency integer
lset  integer  UNIQUE KEY
rset  integer  UNIQUE KEY

এবং ক্যোয়ারী:

SELECT word
FROM lexikon
WHERE lset BETWEEN @Low AND @High
ORDER BY frequency DESC
LIMIT @N

আমি মনে করি একটি প্রচ্ছদ সূচকটি কার্যকর (lset, frequency, word)হবে তবে আমি মনে করি সীমার lsetমধ্যে খুব বেশি মান থাকলে এটি ভাল করতে পারে না (@High, @Low)

একটি সাধারণ সূচকটি (frequency DESC)কখনও কখনও পর্যাপ্তও হতে পারে, যখন সেই সূচকটি ব্যবহার করে কোনও অনুসন্ধান @Nসীমা শুরুর পরে শুরুর দিকে সারি দেয়।

তবে মনে হচ্ছে পারফরম্যান্স প্যারামিটারের মানগুলির উপর অনেক বেশি নির্ভর করে।

(@Low, @High)উচ্চতর ফ্রিকোয়েন্সি শব্দগুলি (সংকীর্ণ) নির্বাচিত পরিসরে ভাগ্যক্রমে রয়েছে কিনা তা নির্বিশেষে পরিসরটি প্রশস্ত বা সংকীর্ণ এবং নির্বিশেষে কীভাবে এটি দ্রুত সম্পাদন করার কোনও উপায় আছে ?

একটি আর-ট্রি / স্থানিক সূচক সাহায্য করবে?

সূচীগুলি যুক্ত করা, ক্যোয়ারিকে পুনরায় লেখা, টেবিলটি নতুন করে ডিজাইন করা, কোনও সীমাবদ্ধতা নেই।


3
কভারিং সূচকগুলি 9.2 (এখন বিটা), বিটিডাব্লু দিয়ে প্রবর্তিত হয়েছে। পোস্টগ্রিএসকিউএল লোকেরা কেবল ইনডেক্স-স্ক্যানের কথা বলে । সম্পর্কিত সম্পর্কিত উত্তরটি দেখুন: dba.stackexchange.com/a/7541/3684 এবং পোস্টগ্র্যাস এসকিউএল উইকি পৃষ্ঠা
এরউইন ব্র্যান্ডসেটেটার

দুটি প্রশ্ন: (1) আপনি টেবিলের জন্য কী ধরণের ব্যবহারের ধরণটি আশা করেন? সেখানে কি বেশিরভাগই পড়ে বা ঘন ঘন আপডেট হয় (বিশেষত নেস্টেট সেট ভেরিয়েবলগুলির)? (২) নেস্টেড সেট ইন্টিজার ভেরিয়েবল lset এবং আরসেট এবং টেক্সট ভেরিয়েবল শব্দের মধ্যে কোনও সংযোগ আছে কি?
জেপি

@ জগ: বেশিরভাগই পঠিত। lset,rsetএবং এর মধ্যে কোনও সংযোগ নেই word
ypercubeᵀᴹ

3
আপনার যদি অনেকগুলি আপডেট থাকে তবে নেস্টেড সেট মডেলটি পারফরম্যান্সের প্রতি শ্রদ্ধার সাথে খারাপ পছন্দ হয়ে উঠবে (যদি আপনার "এসকিউএল অফ আর্ট" বইটিতে অ্যাক্সেস থাকে তবে হাইরাফিক মডেলগুলি সম্পর্কে অধ্যায়টি দেখুন)। তবে যাইহোক, আপনার মূল সমস্যাটি অন্তরস্থলে সর্বাধিক / সর্বোচ্চ মানগুলি (একটি স্বতন্ত্র ভেরিয়েবলের) সন্ধানের অনুরূপ, যার জন্য একটি সূচীকরণ পদ্ধতিটি নকশা করা শক্ত। আমার জানা মতে আপনার সূচকের সবচেয়ে নিকটতম ম্যাচটি হ'ল নঙ্গিস্ট মডিউল, তবে আপনার প্রয়োজন অনুসারে আপনাকে এটি পরিবর্তন করতে হবে। একটি স্থানিক সূচক সহায়ক হওয়ার সম্ভাবনা কম।
জেপি

উত্তর:


30

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

--টেস্টবিডি এবং lexikonডামি ডেটা:

begin;
set role dba;
create role stack;
grant stack to dba;
create schema authorization stack;
set role stack;
--
create table lexikon( _id serial, 
                      word text, 
                      frequency integer, 
                      lset integer, 
                      width_granule integer);
--
insert into lexikon(word, frequency, lset) 
select word, (1000000/row_number() over(order by random()))::integer as frequency, lset
from (select 'word'||generate_series(1,1000000) word, generate_series(1,1000000) lset) z;
--
update lexikon set width_granule=ln(frequency)::integer;
--
create index on lexikon(width_granule, lset);
create index on lexikon(lset);
-- the second index is not used with the function but is added to make the timings 'fair'

granule বিশ্লেষণ (বেশিরভাগ তথ্য এবং সুরের জন্য):

create table granule as 
select width_granule, count(*) as freq, 
       min(frequency) as granule_start, max(frequency) as granule_end 
from lexikon group by width_granule;
--
select * from granule order by 1;
/*
 width_granule |  freq  | granule_start | granule_end
---------------+--------+---------------+-------------
             0 | 500000 |             1 |           1
             1 | 300000 |             2 |           4
             2 | 123077 |             5 |          12
             3 |  47512 |            13 |          33
             4 |  18422 |            34 |          90
             5 |   6908 |            91 |         244
             6 |   2580 |           245 |         665
             7 |    949 |           666 |        1808
             8 |    349 |          1811 |        4901
             9 |    129 |          4926 |       13333
            10 |     47 |         13513 |       35714
            11 |     17 |         37037 |       90909
            12 |      7 |        100000 |      250000
            13 |      2 |        333333 |      500000
            14 |      1 |       1000000 |     1000000
*/
alter table granule drop column freq;
--

প্রথমে উচ্চ ফ্রিকোয়েন্সি স্ক্যান করার জন্য ফাংশন:

create function f(p_lset_low in integer, p_lset_high in integer, p_limit in integer)
       returns setof lexikon language plpgsql set search_path to 'stack' as $$
declare
  m integer;
  n integer := 0;
  r record;
begin 
  for r in (select width_granule from granule order by width_granule desc) loop
    return query( select * 
                  from lexikon 
                  where width_granule=r.width_granule 
                        and lset>=p_lset_low and lset<=p_lset_high );
    get diagnostics m = row_count;
    n = n+m;
    exit when n>=p_limit;
  end loop;
end;$$;

ফলাফল (সময়গুলি সম্ভবত এক চিমটি লবণের সাথে নেওয়া উচিত তবে প্রতিটি ক্যোয়ারী কোনও ক্যাশে প্রতিরোধ করতে দুবার চালানো হয়)

প্রথমে আমরা লিখেছি ফাংশন ব্যবহার:

\timing on
--
select * from f(20000, 30000, 5) order by frequency desc limit 5;
/*
 _id |   word    | frequency | lset  | width_granule
-----+-----------+-----------+-------+---------------
 141 | word23237 |      7092 | 23237 |             9
 246 | word25112 |      4065 | 25112 |             8
 275 | word23825 |      3636 | 23825 |             8
 409 | word28660 |      2444 | 28660 |             8
 418 | word29923 |      2392 | 29923 |             8
Time: 80.452 ms
*/
select * from f(20000, 30000, 5) order by frequency desc limit 5;
/*
 _id |   word    | frequency | lset  | width_granule
-----+-----------+-----------+-------+---------------
 141 | word23237 |      7092 | 23237 |             9
 246 | word25112 |      4065 | 25112 |             8
 275 | word23825 |      3636 | 23825 |             8
 409 | word28660 |      2444 | 28660 |             8
 418 | word29923 |      2392 | 29923 |             8
Time: 0.510 ms
*/

এবং তারপরে একটি সাধারণ সূচক স্ক্যান সহ:

select * from lexikon where lset between 20000 and 30000 order by frequency desc limit 5;
/*
 _id |   word    | frequency | lset  | width_granule
-----+-----------+-----------+-------+---------------
 141 | word23237 |      7092 | 23237 |             9
 246 | word25112 |      4065 | 25112 |             8
 275 | word23825 |      3636 | 23825 |             8
 409 | word28660 |      2444 | 28660 |             8
 418 | word29923 |      2392 | 29923 |             8
Time: 218.897 ms
*/
select * from lexikon where lset between 20000 and 30000 order by frequency desc limit 5;
/*
 _id |   word    | frequency | lset  | width_granule
-----+-----------+-----------+-------+---------------
 141 | word23237 |      7092 | 23237 |             9
 246 | word25112 |      4065 | 25112 |             8
 275 | word23825 |      3636 | 23825 |             8
 409 | word28660 |      2444 | 28660 |             8
 418 | word29923 |      2392 | 29923 |             8
Time: 51.250 ms
*/
\timing off
--
rollback;

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


পূর্ববর্তী স্তরের মধ্য width_granule=8থেকে granulae_startএবং কেন একটি ফাঁক আছে granulae_end?
ভাইগোরভ

@ ভাইগেরভ @ 1809 এবং 1810 এর কোনও মান নেই বলে? এটি এলোমেলোভাবে ডেটা উত্পন্ন হয়েছে তাই ওয়াইএমএমভি :)
জ্যাক ডগলাস

frequencyএইচ এম , মনে হচ্ছে এলোমেলোভাবে কিছু করার নেই, তবে উপায়টি উত্পন্ন হওয়ার সাথে সাথে : 1e6 / 2 এবং 1e6 / 3 এর মধ্যে একটি বড় ফাঁক, উচ্চতর সারির সংখ্যাটি হয়, ছোট ফাঁক হয়। যাইহোক, এই দুর্দান্ত পদ্ধতির জন্য আপনাকে ধন্যবাদ !!
ভাইগোরভ

@ ভাইগোরভ দুঃখিত, হ্যাঁ, আপনি ঠিক বলেছেন। আপনার যদি ইতিমধ্যে না থাকে তবে এরউইনগুলির উন্নতিগুলি একবার দেখে নিন !
জ্যাক ডগলাস

23

সেটআপ

লোকেদের অনুসরণ এবং তুলনা করা আরও সহজ করার জন্য আমি @ জ্যাকের সেটআপটি তৈরি করছি। পোস্টগ্রিসএসকিউএল 9.1.4 এর সাথে পরীক্ষিত ।

CREATE TABLE lexikon (
   lex_id    serial PRIMARY KEY
 , word      text
 , frequency int NOT NULL  -- we'd need to do more if NULL was allowed
 , lset      int
);

INSERT INTO lexikon(word, frequency, lset) 
SELECT 'w' || g  -- shorter with just 'w'
     , (1000000 / row_number() OVER (ORDER BY random()))::int
     , g
FROM   generate_series(1,1000000) g

এখান থেকে আমি একটি পৃথক রুট নিয়ে চলেছি:

ANALYZE lexikon;

সহায়ক টেবিল

এই সমাধানটি মূল টেবিলটিতে কলাম যুক্ত করে না, এটির জন্য কেবলমাত্র একটি ক্ষুদ্র সাহায্যকারী টেবিল প্রয়োজন। আমি এটি স্কিমাতে রেখেছি public, আপনার পছন্দের যেকোন স্কিমা ব্যবহার করুন।

CREATE TABLE public.lex_freq AS
WITH x AS (
   SELECT DISTINCT ON (f.row_min)
          f.row_min, c.row_ct, c.frequency
   FROM  (
      SELECT frequency, sum(count(*)) OVER (ORDER BY frequency DESC) AS row_ct
      FROM   lexikon
      GROUP  BY 1
      ) c
   JOIN  (                                   -- list of steps in recursive search
      VALUES (400),(1600),(6400),(25000),(100000),(200000),(400000),(600000),(800000)
      ) f(row_min) ON c.row_ct >= f.row_min  -- match next greater number
   ORDER  BY f.row_min, c.row_ct, c.frequency DESC
   )
, y AS (   
   SELECT DISTINCT ON (frequency)
          row_min, row_ct, frequency AS freq_min
        , lag(frequency) OVER (ORDER BY row_min) AS freq_max
   FROM   x
   ORDER  BY frequency, row_min
   -- if one frequency spans multiple ranges, pick the lowest row_min
   )
SELECT row_min, row_ct, freq_min
     , CASE freq_min <= freq_max
         WHEN TRUE  THEN 'frequency >= ' || freq_min || ' AND frequency < ' || freq_max
         WHEN FALSE THEN 'frequency  = ' || freq_min
         ELSE            'frequency >= ' || freq_min
       END AS cond
FROM   y
ORDER  BY row_min;

সারণীটি দেখতে এমন দেখাচ্ছে:

row_min | row_ct  | freq_min | cond
--------+---------+----------+-------------
400     | 400     | 2500     | frequency >= 2500
1600    | 1600    | 625      | frequency >= 625 AND frequency < 2500
6400    | 6410    | 156      | frequency >= 156 AND frequency < 625
25000   | 25000   | 40       | frequency >= 40 AND frequency < 156
100000  | 100000  | 10       | frequency >= 10 AND frequency < 40
200000  | 200000  | 5        | frequency >= 5 AND frequency < 10
400000  | 500000  | 2        | frequency >= 2 AND frequency < 5
600000  | 1000000 | 1        | frequency  = 1

যেহেতু কলামটি condআরও নিচে ডায়নামিক এসকিউএল ব্যবহৃত হবে, আপনাকে এই টেবিলটিকে সুরক্ষিত করতে হবে । আপনি যদি কোনও উপযুক্ত বর্তমান সম্পর্কে নিশ্চিত না হতে পারেন তবে সর্বদা সারণিটি স্কিমা-যোগ্য করুন search_pathএবং public(এবং অন্য কোনও অবিশ্বস্ত ভূমিকা) থেকে লেখার সুযোগগুলি প্রত্যাহার করুন :

REVOKE ALL ON public.lex_freq FROM public;
GRANT SELECT ON public.lex_freq TO public;

টেবিলটি lex_freqতিনটি উদ্দেশ্যে কাজ করে:

  • প্রয়োজনীয় আংশিক সূচকগুলি স্বয়ংক্রিয়ভাবে তৈরি করুন ।
  • পুনরাবৃত্তি ফাংশন জন্য পদক্ষেপ সরবরাহ করুন।
  • টিউনিংয়ের জন্য মেটা সম্পর্কিত তথ্য।

ইনডেক্সে

এই DOবিবৃতিটি সমস্ত প্রয়োজনীয় সূচক তৈরি করে :

DO
$$
DECLARE
   _cond text;
BEGIN
   FOR _cond IN
      SELECT cond FROM public.lex_freq
   LOOP
      IF _cond LIKE 'frequency =%' THEN
         EXECUTE 'CREATE INDEX ON lexikon(lset) WHERE ' || _cond;
      ELSE
         EXECUTE 'CREATE INDEX ON lexikon(lset, frequency DESC) WHERE ' || _cond;
      END IF;
   END LOOP;
END
$$

এই সমস্ত আংশিক সূচী একবারে টেবিলটি বিস্তৃত করে। তারা পুরো টেবিলে একটি বেসিক সূচক হিসাবে প্রায় একই আকার:

SELECT pg_size_pretty(pg_relation_size('lexikon'));       -- 50 MB
SELECT pg_size_pretty(pg_total_relation_size('lexikon')); -- 71 MB

এখন পর্যন্ত 50 এমবি টেবিলের জন্য কেবল 21 এমবি সূচক index

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

আংশিক সূচকগুলির জন্য এটি করার কোনও অর্থ নেই যা কেবলমাত্র একটি একক ফ্রিকোয়েন্সি বিস্তৃত। এগুলি এখন চলছে (lset)। তৈরি সূচকগুলি দেখতে দেখতে:

CREATE INDEX ON lexikon(lset, frequency DESC) WHERE frequency >= 2500;
CREATE INDEX ON lexikon(lset, frequency DESC) WHERE frequency >= 625 AND frequency < 2500;
-- ...
CREATE INDEX ON lexikon(lset, frequency DESC) WHERE frequency >= 2 AND frequency < 5;
CREATE INDEX ON lexikon(lset) WHERE freqency = 1;

ক্রিয়া

ফাংশনটি কিছুটা স্টাইলের সাথে @ জ্যাকের সমাধানের মতো:

CREATE OR REPLACE FUNCTION f_search(_lset_min int, _lset_max int, _limit int)
  RETURNS SETOF lexikon
$func$
DECLARE
   _n      int;
   _rest   int := _limit;   -- init with _limit param
   _cond   text;
BEGIN 
   FOR _cond IN
      SELECT l.cond FROM public.lex_freq l ORDER BY l.row_min
   LOOP    
      --  RAISE NOTICE '_cond: %, _limit: %', _cond, _rest; -- for debugging
      RETURN QUERY EXECUTE '
         SELECT * 
         FROM   public.lexikon 
         WHERE  ' || _cond || '
         AND    lset >= $1
         AND    lset <= $2
         ORDER  BY frequency DESC
         LIMIT  $3'
      USING  _lset_min, _lset_max, _rest;

      GET DIAGNOSTICS _n = ROW_COUNT;
      _rest := _rest - _n;
      EXIT WHEN _rest < 1;
   END LOOP;
END
$func$ LANGUAGE plpgsql STABLE;

মূল পার্থক্য:

  • ডায়নামিক এসকিউএল সহ RETURN QUERY EXECUTE
    আমরা পদক্ষেপগুলি লুপ করার সাথে সাথে একটি পৃথক ক্যোয়ারী পরিকল্পনা সুবিধাভোগী হতে পারে। স্ট্যাটিক এসকিউএল এর জন্য ক্যোয়ারী পরিকল্পনাটি একবার উত্পন্ন হয় এবং তারপরে পুনরায় ব্যবহার করা হয় - যা কিছু ওভারহেড সংরক্ষণ করতে পারে। তবে এক্ষেত্রে ক্যোয়ারীটি সহজ এবং মানগুলি খুব আলাদা। ডায়নামিক এসকিউএল একটি বড় জয় হবে।

  • LIMITপ্রতিটি প্রশ্নের পদক্ষেপের জন্য গতিশীল
    এটি একাধিক উপায়ে সহায়তা করে: প্রথমত, সারিগুলি কেবলমাত্র প্রয়োজনীয় হিসাবে আনা হয়। গতিশীল এসকিউএল এর সাথে একত্রে এটি শুরু করতে বিভিন্ন ক্যোয়ারী পরিকল্পনা তৈরি করতে পারে। দ্বিতীয়: LIMITউদ্বৃত্ত ছাঁটাই করতে ফাংশন কলটিতে অতিরিক্ত প্রয়োজন নেই ।

উচ্চতার চিহ্ন

সেটআপ

আমি চারটি উদাহরণ বেছে নিয়েছি এবং প্রত্যেকটির সাথে তিনটি পৃথক পরীক্ষা চালিয়েছি। উষ্ণ ক্যাশের সাথে তুলনা করতে আমি পাঁচটি সেরা নিয়েছি:

  1. ফর্মের কাঁচা এসকিউএল কোয়েরি:

    SELECT * 
    FROM   lexikon 
    WHERE  lset >= 20000
    AND    lset <= 30000
    ORDER  BY frequency DESC
    LIMIT  5;
  2. এই সূচক তৈরির পরে একই

    CREATE INDEX ON lexikon(lset);

    আমার সমস্ত আংশিক সূচক একসাথে একই স্থানের প্রয়োজন:

    SELECT pg_size_pretty(pg_total_relation_size('lexikon')) -- 93 MB
  3. কাজ

    SELECT * FROM f_search(20000, 30000, 5);

ফলাফল

SELECT * FROM f_search(20000, 30000, 5);

1: মোট রানটাইম: 315.458 এমএস
2: মোট রানটাইম: 36.458 এমএস
3: মোট রানটাইম: 0.330 এমএস

SELECT * FROM f_search(60000, 65000, 100);

1: মোট রানটাইম: 294.819 এমএস
2: মোট রানটাইম: 18.915 এমএস
3: মোট রানটাইম: 1.414 এমএস

SELECT * FROM f_search(10000, 70000, 100);

1: মোট রানটাইম: 426.831 এমএস
2: মোট রানটাইম: 217.874 এমএস
3: মোট রানটাইম: 1.611 এমএস

SELECT * FROM f_search(1, 1000000, 5);

1: সর্বমোট রানটাইম: 2458.205 এমএস
2: মোট রানটাইম: 2458.205 এমএস - এলসিটির বড় পরিসরের জন্য, সিক স্ক্যান সূচকের চেয়ে দ্রুত।
3: মোট রানটাইম: 0.266 এমএস

উপসংহার

প্রত্যাশিত হিসাবে, ফাংশনটি থেকে সুবিধাটি আরও বড় lsetএবং আরও ছোট পরিসরের সাথে বৃদ্ধি পায় LIMIT

সঙ্গে খুব ছোট রেঞ্জlset সূচক সঙ্গে একযোগে কাঁচা ক্যোয়ারী আসলে দ্রুত । আপনি পরীক্ষা করতে এবং সম্ভবত শাখা করতে চাইবেন: ছোট রেঞ্জের কাঁচা কোয়েরি lset, অন্যথায় ফাংশন কল। এমনকি আপনি এটি "উভয় বিশ্বের সেরা" জন্য ফাংশনটিতে তৈরি করতে পারেন - আমি এটিই করব।

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


1

শব্দের কলামটি সূচকে অন্তর্ভুক্ত করার কোনও কারণ আমি দেখতে পাচ্ছি না। সুতরাং এই সূচক

CREATE INDEX lexikon_lset_frequency ON lexicon (lset, frequency DESC)

আপনার সম্পাদনাটি দ্রুত সম্পাদন করবে।

UPD

বর্তমানে পোস্টগ্রিসএসকিউএলে একটি কভারিং সূচক তৈরির কোনও উপায় নেই। পোস্টগ্রেএসকিউএল মেলিং তালিকায় এই বৈশিষ্ট্যটি সম্পর্কে আলোচনা হয়েছিল http://archives.postgresql.org/pgsql-performance/2012-06/msg00114.php


1
এটি সূচকে "আচ্ছাদন" করার অন্তর্ভুক্ত ছিল।
ypercubeᵀᴹ

কিন্তু ক্যোয়ারী সিদ্ধান্ত গাছটিতে সেই শব্দটি অনুসন্ধান না করে আপনি কি নিশ্চিত যে আচ্ছাদন সূচকটি এখানে সহায়তা করছে?
jcolebrand

ঠিক আছে, আমি এখন দেখতে। বর্তমানে পোস্টগ্রিসএসকিউএলে একটি কভারিং সূচক তৈরির কোনও উপায় নেই। মেলিং তালিকা সংরক্ষণাগারগুলিতে এই বৈশিষ্ট্যটি নিয়ে আলোচনা হয়েছিল p . পস্টগ্রেসক্ল.আর.এল.পিপসকিএল- দক্ষতা / ২০১২-০6/msg00114.php
গ্রেহেম্প

পোস্টগ্রেএসকিউএল-র "কভারিং ইনডেক্স" সম্পর্কে প্রশ্নটিতে এরউইন ব্র্যান্ডসেট্টারের মন্তব্যও দেখুন।
jp

1

জিআইএসটি সূচক ব্যবহার করা

শীর্ষস্থানীয় ফ্রিকোয়েন্সি শব্দগুলি (সংকীর্ণ) নির্বাচিত পরিসরে ভাগ্যক্রমে রয়েছে কিনা তা নির্বিশেষে, পরিসরটি (@ নীচে, @ উচ্চ) প্রশস্ত বা সংকীর্ণ কিনা তা বিবেচনা না করেই এটি দ্রুত সম্পাদন করার কোনও উপায় আছে কি?

এটি আপনি যখন উপবাস করেন তখন এর অর্থ নির্ভর করে: আপনার ক্যোয়ারী হওয়ায় আপনাকে অবশ্যই স্পষ্টভাবে প্রতিটি সারি দেখতে হবে visit ORDER freq DESC । যদি আমি প্রশ্নটি বুঝতে পারি তবে কোয়েরি পরিকল্পনাকারী এরই মধ্যে লজ্জাবোধ করেছেন,

এখানে আমরা 10k সারিগুলির একটি সারণী তৈরি করব (5::int,random()::double precision)

CREATE EXTENSION IF NOT EXISTS btree_gin;
CREATE TABLE t AS
  SELECT 5::int AS foo, random() AS bar
  FROM generate_series(1,1e4) AS gs(x);

আমরা এটি সূচক,

CREATE INDEX ON t USING gist (foo, bar);
ANALYZE t;

আমরা এটিকে জিজ্ঞাসা করি,

EXPLAIN ANALYZE
SELECT *
FROM t
WHERE foo BETWEEN 1 AND 6
ORDER BY bar DESC
FETCH FIRST ROW ONLY;

আমরা একটি পেতে Seq Scan on t । এটি কেবল কারণ আমাদের নির্বাচিততার প্রাক্কলন অনুসারে পিজি উপসংহারটি শেষ করতে দেয় কোনও সূচি স্ক্যান করা এবং পুনরায় পরীক্ষা করার চেয়ে গতি অ্যাক্সেসটি দ্রুত। সুতরাং আমরা এর আরও 1,000,000 সারি সন্নিবেশ করিয়ে এটিকে আরও সরস করে তুলি (42::int,random()::double precision)যা আমাদের "পরিসীমা" ফিট করে না।

INSERT INTO t(foo,bar)
SELECT 42::int, x
FROM generate_series(1,1e6) AS gs(x);

VACUUM ANALYZE t;

এবং তারপর আমরা জিজ্ঞাসা,

EXPLAIN ANALYZE
SELECT *
FROM t
WHERE foo BETWEEN 1 AND 6
ORDER BY bar DESC
FETCH FIRST ROW ONLY;

আপনি এখানে দেখতে পারেন আমরা একটি সাথে 4.6 এমএসে সম্পূর্ণ করি কেবলমাত্র সূচক স্ক্যান ,

                                                                 QUERY PLAN                                                                  
---------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=617.64..617.64 rows=1 width=12) (actual time=4.652..4.652 rows=1 loops=1)
   ->  Sort  (cost=617.64..642.97 rows=10134 width=12) (actual time=4.651..4.651 rows=1 loops=1)
         Sort Key: bar DESC
         Sort Method: top-N heapsort  Memory: 25kB
         ->  Index Only Scan using t_foo_bar_idx on t  (cost=0.29..566.97 rows=10134 width=12) (actual time=0.123..3.623 rows=10000 loops=1)
               Index Cond: ((foo >= 1) AND (foo <= 6))
               Heap Fetches: 0
 Planning time: 0.144 ms
 Execution time: 4.678 ms
(9 rows)

পুরো টেবিলটি অন্তর্ভুক্ত করার জন্য ব্যাপ্তিটি প্রসারিত করে, আরও একটি সেক স্ক্যান তৈরি করে - যৌক্তিকভাবে, এবং আরও এক বিলিয়ন সারি দিয়ে বৃদ্ধি করা অন্য সূচক স্ক্যান তৈরি করতে পারে।

সুতরাং সংক্ষেপে,

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