অনাকাঙ্ক্ষিত নেস্ট লুপ বনাম হ্যাশ পোস্টগ্রিএসকিউএল 9.6 এ যোগ দিন


13

পোস্টগ্র্রেএসকিউএল 9.6 কোয়েরি পরিকল্পনায় আমার একটি সমস্যা হয়েছে। আমার জিজ্ঞাসাটি এমন দেখাচ্ছে:

SET role plain_user;

SELECT properties.*
FROM properties
JOIN entries_properties
  ON properties.id = entries_properties.property_id
JOIN structures
  ON structures.id = entries_properties.entry_id 
WHERE structures."STRUKTURBERICHT" != ''
  AND properties."COMPOSITION" LIKE 'Mo%'
  AND (
    properties."NAME" LIKE '%VASP-ase-preopt%'
    OR properties."CALCULATOR_ID" IN (7,22,25)
  )
AND properties."TYPE_ID" IN (6)

আমি উপরের ব্যবহৃত টেবিলগুলির জন্য সারি-স্তরের সুরক্ষা সক্ষম করেছি।

  • এর সাথে set enable_nestloop = True, ক্যোয়ারির পরিকল্পনাকারী মোট 37 টি সেকেন্ডের চলমান সময়ের সাথে নেস্টেড লুপটিতে যোগদান করে: https://explain.depesz.com/s/59BR

  • এর সাথে set enable_nestloop = False, হ্যাশ যোগদানের পদ্ধতিটি ব্যবহৃত হয় এবং ক্যোয়ারির সময়টি প্রায় 0.3 সেকেন্ড: https://explain.depesz.com/s/PG8E

VACUUM ANALYZEকোয়েরিগুলি চালানোর আগে আমি করেছি , তবে তাতে কোনও লাভ হয়নি।

আমি জানি যে এটির জন্য একটি ভাল অনুশীলন নয় set enable_nestloop = Falseএবং পরিকল্পনাকারীর জন্য অন্য কোনও অনুরূপ বিকল্প। তবে আমি কীভাবে পরিকল্পনাকারীকে নেস্ট লুপগুলি অক্ষম না করে হ্যাশ যোগ দিতে ব্যবহার করতে "বোঝাতে" পারি?

ক্যোয়ারিতে পুনর্লিখন করা একটি বিকল্প।

যদি আমি এমন কোনও ক্যোয়ারী চালান যে কোনও ভূমিকার অধীনে আরএলএসকে ছাড়িয়ে যায়, তবে এটি খুব দ্রুত কার্যকর করা হয়। সারি-স্তরের সুরক্ষা নীতিটি দেখে মনে হচ্ছে:

CREATE POLICY properties_select
ON properties
FOR SELECT
USING (
  (
    properties.ouid = get_current_user_id()
    AND properties.ur
  )
  OR (
    properties.ogid in (select get_current_groups_id())
    AND properties.gr
  )
  OR properties.ar
);

কোন ধারণা বা পরামর্শ ব্যাপকভাবে প্রশংসা হবে।


কিছুটা বিভ্রান্ত: কেন আছে AND properties."TYPE_ID" IN (6);এবং নেই = 6;?
Vérace

2
@ ভ্যারেস = যখন আরও প্রশস্তভাবে ব্যবহৃত হয়, তারা উভয় একইভাবে প্লাড হয়ে যায়। আমার ধারনা হ'ল তিনি একাধিক মান নিয়ে খেলছেন, বা একটি ওআরএম খুব অলস হয়ে উঠছে।
ইভান ক্যারল

উত্তর:


15

এখানে যা ঘটছে তা হল একদিকে নেস্টেড লুপ। নেস্টেড লুপগুলি সত্যই ভাল কাজ করে যখন একপাশে খুব ছোট থাকে যেমন এক সারি ফিরে আসা। আপনার ক্যোয়ারিতে, পরিকল্পনাকারী এখানে বোমল করে এবং অনুমান করে যে কোনও হ্যাশ জোড় মাত্র একটি সারি ফিরে আসবে। পরিবর্তে, সেই হ্যাশ যোগ দিন (সম্পত্তি_id = id) 1,338 টি সারি প্রদান করে। এটি নেস্টেড লুপের অন্যদিকে চালাতে 1,338 লুপকে বাধ্য করে যা ইতিমধ্যে 3,444 সারি রয়েছে। এটি হেল্লা-লট যখন আপনি কেবলমাত্র একজনের প্রত্যাশা করেন (যা "লুপ" এর থেকেও বেশি নয়)। Anywayy ..

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

Filter: (((properties."COMPOSITION")::text ~~ 'Mo%'::text) AND (((properties."NAME")::text ~~ '%VASP-ase-preopt%'::text) OR (properties."CALCULATOR_ID" = ANY ('{7,22,25}'::integer[]))))

PostgreSQL আশা করে যে এটি একটি সারিতে ফিরে আসবে। তবে তা হয় না। এবং, এটি আসলে আপনার সমস্যা। সুতরাং এখানে কিছু বিকল্প, এটি একটি স্লেজ হাতুড়ি গ্রহণ এবং অক্ষম জড়িত নাnested_loop

  • propertiesসিক স্ক্যানটি সম্পূর্ণভাবে এড়িয়ে যেতে, বা প্রত্যাবর্তনের আরও ভাল অনুমান করতে আপনি এটিতে একটি সূচক বা দুটি যুক্ত করতে পারেন।

    CREATE INDEX ON properties USING ( "TYPE_ID", "CALCULATOR_ID" );
    -- the gist_trgm_ops may or may not be needed depending on selectivity of above.
    CREATE INDEX ON properties USING GIST (
      "COMPOSITION" gist_trgm_ops,
      "NAME"        gist_trgm_ops
    );
    ANALYZE properties;
    
  • বিকল্পভাবে, আপনি বৈশিষ্ট্যগুলি স্টাফগুলিকে একটি সিটিইতে স্থানান্তর করতে পারেন বা সাবলেট করতে পারেন OFFSET 0যা দিয়ে বেড়া তৈরি করে।

    WITH t AS (
      SELECT *
      FROM properties.
      WHERE "COMPOSITION" LIKE 'Mo%'
      AND (
        "NAME" LIKE '%VASP-ase-preopt%'
        OR "CALCULATOR_ID" IN (7,22,25)
      )
      AND "TYPE_ID" IN (6)
    )
    SELECT * FROM structures
    JOIN t ON (
      structures.id = entries_properties.entry_id
    )
    
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.