সূচক স্ক্যানের পরিবর্তে পোস্টগ্রিসএসকিউএল সিক্যুয়ালিয়াল স্ক্যান কেন?


12

হাই সবই আমার আমার পোস্টগ্রিজ এসকিউএল ডাটাবেস ক্যোয়ারিতে সমস্যা হয়েছে এবং ভাবছে যে কেউ সাহায্য করতে পারে কিনা। কিছু পরিস্থিতিতে আমার জিজ্ঞাসাটি সূচকটিকে উপেক্ষা করবে যা আমি তৈরি করেছি যা দুটি সারণীতে যোগদানের জন্য ব্যবহৃত হয় dataএবং data_area। এটি যখন ঘটে তখন এটি ক্রমিক স্ক্যান ব্যবহার করে এবং খুব ধীর অনুসন্ধানের ফলাফল দেয় in

সিক্যুয়াল স্ক্যান ((5 মিনিট)

Unique  (cost=15368261.82..15369053.96 rows=200 width=1942) (actual time=301266.832..301346.936 rows=153812 loops=1)
   CTE data
     ->  Bitmap Heap Scan on data  (cost=6086.77..610089.54 rows=321976 width=297) (actual time=26.286..197.625 rows=335130 loops=1)
           Recheck Cond: (datasetid = 1)
           Filter: ((readingdatetime >= '1920-01-01 00:00:00'::timestamp without time zone) AND (readingdatetime <= '2013-03-11 00:00:00'::timestamp without time zone) AND (depth >= 0::double precision) AND (depth <= 99999::double precision))
           ->  Bitmap Index Scan on data_datasetid_index  (cost=0.00..6006.27 rows=324789 width=0) (actual time=25.462..25.462 rows=335130 loops=1)
                 Index Cond: (datasetid = 1)
   ->  Sort  (cost=15368261.82..15368657.89 rows=158427 width=1942) (actual time=301266.829..301287.110 rows=155194 loops=1)
         Sort Key: data.id
         Sort Method: quicksort  Memory: 81999kB
         ->  Hash Left Join  (cost=15174943.29..15354578.91 rows=158427 width=1942) (actual time=300068.588..301052.832 rows=155194 loops=1)
               Hash Cond: (data_area.area_id = area.id)
               ->  Hash Join  (cost=15174792.93..15351854.12 rows=158427 width=684) (actual time=300066.288..300971.644 rows=155194 loops=1)
                     Hash Cond: (data.id = data_area.data_id)
                     ->  CTE Scan on data  (cost=0.00..6439.52 rows=321976 width=676) (actual time=26.290..313.842 rows=335130 loops=1)
                     ->  Hash  (cost=14857017.62..14857017.62 rows=25422025 width=8) (actual time=300028.260..300028.260 rows=26709939 loops=1)
                           Buckets: 4194304  Batches: 1  Memory Usage: 1043357kB
                           ->  Seq Scan on data_area  (cost=0.00..14857017.62 rows=25422025 width=8) (actual time=182921.056..291687.996 rows=26709939 loops=1)
                                 Filter: (area_id = ANY ('{28,29,30,31,32,33,25,26,27,18,19,20,21,12,13,14,15,16,17,34,35,1,2,3,4,5,6,22,23,24,7,8,9,10,11}'::integer[]))
               ->  Hash  (cost=108.49..108.49 rows=3349 width=1258) (actual time=2.256..2.256 rows=3349 loops=1)
                     Buckets: 1024  Batches: 1  Memory Usage: 584kB
                     ->  Seq Scan on area  (cost=0.00..108.49 rows=3349 width=1258) (actual time=0.007..0.666 rows=3349 loops=1)
 Total runtime: 301493.379 ms

সূচক স্ক্যান (~ 3 সেকেন্ড) ( ব্যাখ্যা.ডেপস.কম এ )

Unique  (cost=17352256.47..17353067.50 rows=200 width=1942) (actual time=3603.303..3681.619 rows=153812 loops=1)
   CTE data
     ->  Bitmap Heap Scan on data  (cost=6284.60..619979.56 rows=332340 width=297) (actual time=26.201..262.314 rows=335130 loops=1)
           Recheck Cond: (datasetid = 1)
           Filter: ((readingdatetime >= '1920-01-01 00:00:00'::timestamp without time zone) AND (readingdatetime <= '2013-03-11 00:00:00'::timestamp without time zone) AND (depth >= 0::double precision) AND (depth <= 99999::double precision))
           ->  Bitmap Index Scan on data_datasetid_index  (cost=0.00..6201.51 rows=335354 width=0) (actual time=25.381..25.381 rows=335130 loops=1)
                 Index Cond: (datasetid = 1)
   ->  Sort  (cost=17352256.47..17352661.98 rows=162206 width=1942) (actual time=3603.302..3623.113 rows=155194 loops=1)
         Sort Key: data.id
         Sort Method: quicksort  Memory: 81999kB
         ->  Hash Left Join  (cost=1296.08..17338219.59 rows=162206 width=1942) (actual time=29.980..3375.921 rows=155194 loops=1)
               Hash Cond: (data_area.area_id = area.id)
               ->  Nested Loop  (cost=0.00..17334287.66 rows=162206 width=684) (actual time=26.903..3268.674 rows=155194 loops=1)
                     ->  CTE Scan on data  (cost=0.00..6646.80 rows=332340 width=676) (actual time=26.205..421.858 rows=335130 loops=1)
                     ->  Index Scan using data_area_pkey on data_area  (cost=0.00..52.13 rows=1 width=8) (actual time=0.006..0.008 rows=0 loops=335130)
                           Index Cond: (data_id = data.id)
                           Filter: (area_id = ANY ('{28,29,30,31,32,33,25,26,27,18,19,20,21,12,13,14,15,16,17,34,35,1,2,3,4,5,6,22,23,24,7,8,9,10,11}'::integer[]))
               ->  Hash  (cost=1254.22..1254.22 rows=3349 width=1258) (actual time=3.057..3.057 rows=3349 loops=1)
                     Buckets: 1024  Batches: 1  Memory Usage: 584kB
                     ->  Index Scan using area_primary_key on area  (cost=0.00..1254.22 rows=3349 width=1258) (actual time=0.012..1.429 rows=3349 loops=1)
 Total runtime: 3706.630 ms

টেবিল কাঠামো

এটি টেবিলের জন্য টেবিল কাঠামো data_area। প্রয়োজনে অন্যান্য টেবিলগুলি সরবরাহ করতে পারি।

CREATE TABLE data_area
(
  data_id integer NOT NULL,
  area_id integer NOT NULL,
  CONSTRAINT data_area_pkey PRIMARY KEY (data_id , area_id ),
  CONSTRAINT data_area_area_id_fk FOREIGN KEY (area_id)
      REFERENCES area (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT data_area_data_id_fk FOREIGN KEY (data_id)
      REFERENCES data (id) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE
);

প্রশ্ন

WITH data AS (
    SELECT * 
    FROM data 
    WHERE 
        datasetid IN (1) 
        AND (readingdatetime BETWEEN '1920-01-01' AND '2013-03-11') 
        AND depth BETWEEN 0 AND 99999
)
SELECT * 
FROM ( 
    SELECT DISTINCT ON (data.id) data.id, * 
    FROM 
        data, 
        data_area 
        LEFT JOIN area ON area_id = area.id 
    WHERE 
        data_id = data.id 
        AND area_id IN (28,29,30,31,32,33,25,26,27,18,19,20,21,12,13,14,15,16,17,34,35,1,2,3,4,5,6,22,23,24,7,8,9,10,11) 
) as s;

153812সারি ফেরত দেয় । কি set enable_seqscan= false;নিষ্ক্রিয় অনুক্রমিক স্ক্যান করতে এবং সূচক ফলাফল পেতে।

আমি ANALYSEডাটাবেসটিতে কিছু করার চেষ্টা করেছি এবং ক্যোয়ারীতে ব্যবহৃত কলামগুলিতে সংগৃহীত পরিসংখ্যান বাড়িয়েছি, তবে কিছুই সাহায্য করছে বলে মনে হচ্ছে না।

কেউ কি এই সম্পর্কে ছড়িয়ে পড়ে এবং আলোকপাত করতে পারে বা আমার চেষ্টা করা উচিত অন্য কিছু প্রস্তাব দিতে পারে?


আপনি যদি সেই কার্যকরকরণ পরিকল্পনাগুলির প্রত্যেকটিকে উত্পন্ন করে এমন প্রশ্নগুলি অন্তর্ভুক্ত করেন তবে এটি আমাকে সহায়তা করবে ।
মাইক শেরিল 'ক্যাট রিক্যাল'

সারিগুলির আনুমানিক সংখ্যা এবং সারিগুলির প্রকৃত সংখ্যায় 2 আদেশের মাত্রার পার্থক্য? আমি কি ঠিক পড়ছি?
মাইক শেরিল 'ক্যাট রিক্যাল'

@ ক্যাটাক্যাল ক্যোয়ারী যুক্ত করেছে (কী চলছে তা কার্যকর করার জন্য মৌলিক মৌলিক)। আপনি যখন আনুমানিক সারিগুলি উল্লেখ করেন তা কি 200 এবং এরপরে এটি 153812 আসবে?
মার্ক ডেভিডসন

2
হ্যাঁ, 200 বনাম 150 ক এক নজরে অদ্ভুত বলে মনে হচ্ছে। কার্টেসিয়ান পণ্য ( FROM data, data_area) এর সাথে বাম জোড়ের মিশ্রণের কোনও বাধ্যতামূলক কারণ আছে ? প্রথম নজরে, DISTINCT অন অর্ডার বাই দফা ব্যতীত ব্যবহার করা একটি খারাপ ধারণা বলে মনে হচ্ছে।
মাইক শেরিল 'ক্যাট রিক্যাল'

উত্তর:


8

এই লাইনটি লক্ষ্য করুন:

->  Index Scan using data_area_pkey on data_area  (cost=0.00..52.13 rows=1 width=8) 
    (actual time=0.006..0.008 rows=0 loops=335130)

আপনি যদি লুপগুলি বিবেচনা করে মোট ব্যয় গণনা করেন তবে তা হয় 52.3 * 335130 = 17527299। এটি বিকল্পের জন্য 14857017.62 এর চেয়ে বড় seq_scan। এজন্য এটি সূচকটি ব্যবহার করে না।

সুতরাং অপ্টিমাইজার সূচক স্ক্যানের ব্যয়কে বেশি মূল্যায়ন করছে। আমি অনুমান করতে পারি যে আপনার তথ্য সূচকে সাজানো হয়েছে (হয় ক্লাস্টারড ইনডেক্সের কারণে বা এটি কীভাবে লোড হয়েছিল) এবং / অথবা আপনার প্রচুর পরিমাণে ক্যাশ মেমরি এবং / অথবা একটি দুর্দান্ত ফাস্ট ডিস্ক রয়েছে। অতএব সামান্য এলোমেলো I / O চলছে।

এছাড়াও আপনি পরীক্ষা করা উচিত correlationমধ্যে pg_stats, যে অপটিমাইজার দ্বারা ব্যবহৃত হয় সূচক খরচ কম্পিউটিং যখন ক্লাস্টারিং মূল্যায়ন করার, এবং পরিশেষে পরিবর্তনের চেষ্টা random_page_costএবং cpu_index_tuple_costআপনার সিস্টেম মেলে।


আমি যদি কিছু মিস না করি তবে আমার মনে হয় @ জোপ মানে 52.13, না 52.3, যার ফলস্বরূপ 17470326.9 (সিক_স্ক্যানের চেয়ে এখনও বড়)
বটনেট

2

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

আমি যা চেষ্টা করব তা হ'ল ক্যোরিয়াকে যথাসম্ভব সরল করে লিখতে হবে:

SELECT d.id, * 
FROM 
    data d 
    JOIN data_area da ON da.data_id = d.id
    LEFT JOIN area a ON da.area_id = a.id 
WHERE 
    d.datasetid IN (1) 
    AND da.area_id IN (28,29,30,31,32,33,25,26,27,18,19,20,21,12,13,14,15,16,17,34,35,1,2,3,4,5,6,22,23,24,7,8,9,10,11) 
    AND (readingdatetime BETWEEN '1920-01-01' AND '2013-03-11') -- this and the next condition don't do anything, I think
    AND depth BETWEEN 0 AND 99999
;

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

দয়া করে ফিরে প্রতিবেদন করুন এবং আপনি কোন পোস্টগ্রাসএসকিউএল সংস্করণ ব্যবহার করেন তা আমাদের জানান।


আপনার পরামর্শের জন্য ধন্যবাদ, আপনার পোস্টে দেরি করা জবাবের জন্য দুঃখিত, আমি অন্যান্য প্রকল্পে কাজ করছি on আপনার পরামর্শটির সত্যই এই অর্থ নেই যে ক্যোয়ারী এখন সমস্ত প্রশ্নের জন্য নির্ভরযোগ্যভাবে সূচকটি ব্যবহার করছে বলে মনে হচ্ছে তবে আমি এখনও এর সাথে যে পারফরম্যান্স আশা করব তা পাচ্ছি না। আমি এমন একটি ক্যোয়ারিতে একটি বিশ্লেষণ করেছি যাতে আরও অনেক তথ্য রয়েছে d ডেপেস্জেস / এস / ১ ইউ আইএনডিএক্স স্ক্যানে 95% সময় ব্যয় করে 4 মিনিটের মতো সময় নেয়।
মার্ক ডেভিডসন

উল্লেখ করতে ভুলে গেছি আমি 9.1.4 সংস্করণটি ব্যবহার করছি
মার্ক ডেভিডসন

মূলত সূচক স্ক্যানটি বেশ দ্রুত, সমস্যাটি এটি কয়েক মিলিয়ন বার পুনরাবৃত্তি হয়। SET enable_nestloop=offকোয়েরি চালানোর আগে আপনি কী পাবেন ?
dezso

-1

অনুগামীদের জন্য, আমার মতো একই সমস্যা ছিল

select * from table where bigint_column between x and y and mod(bigint_column, 10000) == z

সমস্যাটি হ'ল আমার বিগিন্ট_ক্লম "x এবং y" এর মধ্যে একটি সূচক ছিল তবে আমার ক্যোয়ারীটি মূলত সেই টেবিলে "সমস্ত সারি" ছিল, সুতরাং এটি সূচীটি ব্যবহার করছে না [যেহেতু এটি পুরো টেবিলটি স্ক্যান করতে হয়েছিল] তবে তবে একটি seq_scan ক্রমিক ক্রম ছিল। আমার জন্য স্থির ছিল সমীকরণের "মোড" দিকের জন্য একটি নতুন সূচক তৈরি করা, যাতে এটি কোনও অভিব্যক্তিতে ব্যবহার করতে পারে ।


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