পোস্টগ্রিসে উইন্ডো ফাংশনের সমষ্টি কীভাবে পাব?


11

আমার কাছে দুটি কলামের ক্রম / পূর্ণসংখ্যার অ্যারের সংমিশ্রণ এবং একটি তৃতীয় কলামে একটি মান রয়েছে এমন একটি টেবিল রয়েছে:

CREATE TABLE foo
(
  perm integer[] NOT NULL,
  combo integer[] NOT NULL,
  value numeric NOT NULL DEFAULT 0
);
INSERT INTO foo
VALUES
( '{3,1,2}', '{1,2,3}', '1.1400' ),
( '{3,1,2}', '{1,2,3}', '0' ),
( '{3,1,2}', '{1,2,3}', '1.2680' ),
( '{3,1,2}', '{1,2,3}', '0' ),
( '{3,1,2}', '{1,2,3}', '1.2680' ),
( '{3,1,2}', '{1,2,3}', '0' ),
( '{3,1,2}', '{1,2,3}', '0' ),
( '{3,1,2}', '{1,2,3}', '1.2680' ),
( '{3,1,2}', '{1,2,3}', '0.9280' ),
( '{3,1,2}', '{1,2,3}', '0' ),
( '{3,1,2}', '{1,2,3}', '1.2680' ),
( '{3,1,2}', '{1,2,3}', '0' ),
( '{3,1,2}', '{1,2,3}', '0' ),
( '{3,1,2}', '{1,2,3}', '1.2680' ),
( '{3,1,2}', '{1,2,3}', '0' ),
( '{3,2,1}', '{1,2,3}', '0' ),
( '{3,2,1}', '{1,2,3}', '0.8000' )

আমি প্রতিটি অনুক্রমের পাশাপাশি প্রতিটি সংমিশ্রণের জন্য গড় এবং মানক বিচ্যুতিটি জানতে চাই। আমি এই প্রশ্নের সাথে এটি করতে পারি:

SELECT
  f1.perm,
  f2.combo,
  f1.perm_average_value,
  f2.combo_average_value,
  f1.perm_stddev,
  f2.combo_stddev,
  f1.perm_count,
  f2.combo_count
FROM
(
  SELECT
    perm,
    combo,
    avg( value ) AS perm_average_value,
    stddev_pop( value ) AS perm_stddev,
    count( * ) AS perm_count
  FROM foo
  GROUP BY perm, combo
) AS f1
JOIN
(
  SELECT
    combo,
    avg( value ) AS combo_average_value,
    stddev_pop( value ) AS combo_stddev,
    count( * ) AS combo_count
  FROM foo
  GROUP BY combo
) AS f2 ON ( f1.combo = f2.combo );

যাইহোক, আমার কাছে প্রচুর ডেটা থাকলে এই ক্যোয়ারীটি বেশ ধীর হয়ে যেতে পারে, কারণ "ফু" টেবিলটি (যা বাস্তবে প্রায় 4 মিলিয়ন সারি সহ 14 টি পার্টিশন নিয়ে গঠিত) দু'বার স্ক্যান করা দরকার।

সম্প্রতি, আমি শিখেছি যে পোস্টগ্র্রেস "উইন্ডো ফাংশনগুলি" সমর্থন করে যা মূলত একটি নির্দিষ্ট কলামের জন্য গ্রুপ বাই এর মতো। এগুলি ব্যবহার করতে আমি আমার ক্যোয়ারীটি পরিবর্তন করেছি:

SELECT
  perm,
  combo,
  avg( value ) as perm_average_value,
  avg( avg( value ) ) over w_combo AS combo_average_value,
  stddev_pop( value ) as perm_stddev,
  stddev_pop( avg( value ) ) over w_combo as combo_stddev,
  count( * ) as perm_count,
  sum( count( * ) ) over w_combo AS combo_count
FROM foo
GROUP BY perm, combo
WINDOW w_combo AS ( PARTITION BY combo );

এটি "কম্বো_কাউন্ট" কলামের জন্য কাজ করার সময়, "কম্বো_ভেরেজ_ভ্যালু" এবং "কম্বো_স্টেদেব" কলামগুলি আর সঠিক নয়। দেখা যাচ্ছে যে প্রতিটি ক্রম ছাড়ার জন্য গড় নেওয়া হচ্ছে এবং তারপরে প্রতিটি সংমিশ্রনের জন্য দ্বিতীয়বার গড় গড়ে নেওয়া হচ্ছে, যা ভুল।

আমি এটা কিভাবে ঠিক করবো? উইন্ডো ফাংশন এমনকি এখানে একটি অপ্টিমাইজেশন হিসাবে ব্যবহার করা যেতে পারে?


বর্তমান সংস্করণ 9.2 পোস্টগ্রেস ধরে নিচ্ছেন? উইন্ডো ফাংশন 8.4 সঙ্গে আসে।
এরউইন ব্র্যান্ডসটেটার

দুঃখিত, আমি নির্দিষ্ট করতে ভুলে গেছি হ্যাঁ আমি সর্বশেষ ব্যবহার করছি, পোস্টগ্রিজ 9.2.4।
স্কট ছোট

উত্তর:


9

আপনার একক ক্যোয়ারী স্তরে সামগ্রিক ফাংশনের ফলাফলের উইন্ডো ফাংশন থাকতে পারে।

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

SELECT perm
      ,combo
      ,avg(value)                 AS perm_average_value
      ,sum(avg(value) * count(*)) OVER w_combo /
       sum(count(*)) OVER w_combo AS combo_average_value
      ,stddev_pop(value)          AS perm_stddev
      ,0                          AS combo_stddev  -- doesn't work!
      ,count(*)                   AS perm_count
      ,sum(count(*)) OVER w_combo AS combo_count
FROM   foo
GROUP  BY perm, combo
WINDOW w_combo  AS (PARTITION BY combo);

জন্য combo_average_valueআপনি এই অভিব্যক্তি হবে

sum(avg(value) * count(*)) OVER w_combo / sum(count(*)) OVER w_combo

যেহেতু আপনার একটি ওজনযুক্ত গড় প্রয়োজন । (১০ সদস্য বিশিষ্ট একটি গ্রুপের গড় ওজনের মাত্র ২ জন সদস্যের একটি গ্রুপের গড়ের চেয়ে বেশি ওজন হয়!)

এটি কাজ করে :

SELECT DISTINCT ON (perm, combo)
       perm
      ,combo
      ,avg(value)        OVER wpc AS perm_average_value
      ,avg(value)        OVER wc  AS combo_average_value
      ,stddev_pop(value) OVER wpc AS perm_stddev
      ,stddev_pop(value) OVER wc  AS combo_stddev
      ,count(*)          OVER wpc AS perm_count
      ,count(*)          OVER wc  AS combo_count
FROM   foo
WINDOW wc  AS (PARTITION BY combo)
      ,wpc AS (PARTITION BY perm, combo);

আমি এখানে দুটি পৃথক উইন্ডো ব্যবহার করছি, এবং DISTINCTউইন্ডো ফাংশন পরেও প্রয়োগ করা সারিগুলি হ্রাস করব ।

তবে আমি গুরুতরভাবে সন্দেহ করি যে এটি আপনার মূল প্রশ্নের চেয়ে দ্রুত হবে। আমি নিশ্চিত যে এটি না।

পরিবর্তিত টেবিল বিন্যাসের সাথে আরও ভাল পারফরম্যান্স

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

CREATE TABLE combo ( 
  combo_id serial PRIMARY KEY
 ,combo    int[] NOT NULL
);

CREATE TABLE perm ( 
  perm_id  serial PRIMARY KEY
 ,perm     int[] NOT NULL
);

CREATE TABLE value (
  perm_id  int REFERENCES perm(perm_id)
 ,combo_id int REFERENCES combo(combo_id)
 ,value numeric NOT NULL DEFAULT 0
);

আপনার যদি রেফারেন্সিয়াল অখণ্ডতার প্রয়োজন না হয় তবে আপনি বিদেশী কী সীমাবদ্ধতাগুলি বাদ দিতে পারেন।

সংযোগটি combo_idটেবিলের মধ্যেও স্থাপন করা যেতে পারে perm, তবে এই দৃশ্যে আমি এটি valueভালভাবে সম্পাদনের জন্য (সামান্য ডি-নরমালাইজড) রাখতে পারি ।

এর ফলস্বরূপ 32 বাইটের সারি আকারের আকার (টিউপল হেডার + প্যাডিং: 24 বাইট, 2 এক্স ইন্ট (8 বাইট), কোনও প্যাডিং) নয়, এবং আপনার numericকলামের অজানা আকার । (আপনার যদি চূড়ান্ত নির্ভুলতার প্রয়োজন না হয় তবে একটি double precisionবা এমনকি একটি realকলামও করতে পারে))

এসও বা এখানে সম্পর্কিত সম্পর্কিত শারীরিক স্টোরেজ সম্পর্কিত আরও :
পড়ার পারফরম্যান্সের জন্য পোস্টগ্রেএসকিউএল কনফিগার করা

যাইহোক, এটি আপনার কাছে এখন যা কেবল তার একটি ভগ্নাংশ এবং একা আকারে আপনার ক্যোয়ারীটিকে আরও দ্রুত তৈরি করবে would সাধারণ সংখ্যায় গোষ্ঠীকরণ এবং বাছাই করাও অনেক দ্রুত।

আপনি প্রথমে একটি subquery একত্রিত এবং তারপরেperm এবং comboসেরা পারফরম্যান্স জন্য যোগ দিতে হবে ।


পরিষ্কার এবং সংক্ষিপ্ত উত্তরের জন্য আপনাকে ধন্যবাদ। আপনি সঠিক, এটি দেখে মনে হবে এভাবে কোনও উপসেট জনগোষ্ঠীর মানক বিচ্যুতি পাওয়ার কোনও উপায় নেই। বলা হচ্ছে, আমি আপনার সমাধানের সরলতা পছন্দ করি। গ্রুপের মাধ্যমে মুছে ফেলা ফলস্বরূপ ক্যোয়ারিকে আরও পাঠযোগ্য। দুর্ভাগ্যক্রমে আপনি সন্দেহ করেছেন যে পারফরম্যান্সটি উপ-সমান। ৩০ মিনিটেরও বেশি সময় চলার পরে আমাকে ক্যোরিটি মেরে ফেলতে হয়েছিল।
স্কট ছোট

@ স্কটস্মল: আপনি পারফরম্যান্সের জন্য কিছু করতে পারেন ... উত্তর দেওয়ার জন্য আপডেট দেখুন।
এরউইন ব্র্যান্ডসটেটার

আমার প্রশ্নটি সহজ করার জন্য, আমি fooটেবিল থেকে কলামগুলি প্রাসঙ্গিক নয় সরিয়েছি । বাস্তবে, আরও কয়েকটি কলাম রয়েছে যা এই ক্যোয়ারী দ্বারা ব্যবহৃত হয় না, তাই আমি নিশ্চিত নই যে এই বিশেষ ব্যবহারের ক্ষেত্রে ক্রম এবং সংমিশ্রণগুলিকে সাধারণকরণ একটি গতির গতি বাড়িয়ে তুলবে।
স্কট ছোট

এছাড়াও, প্রতিটি ক্রমগতি এবং সংমিশ্রণটি পূর্ণসংখ্যার মানগুলি ডিবিতে অন্য একটি টেবিল থেকে আসে। এই ডেটা প্রাক-উত্পাদনের গণনা ব্যয়বহুল। পারম / কম্বোয়ের সর্বাধিক দৈর্ঘ্য 5, তবে 5Pn এবং 5Cn এন এর বৃহত মানগুলির জন্য বর্তমানে বড় আকারে বেড়েছে (বর্তমানে প্রায় 1000, তবে প্রতিদিন বাড়ছে) ... যাইহোক, এটি আরও একটি দিনের প্রশ্ন day আপনার সমস্ত সহায়তার জন্য আবার ধন্যবাদ
স্কট ছোট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.