পোস্টগ্রিসে বাল্ক সন্নিবেশ করার দ্রুততম কোনটি?


242

পোস্টোগ্রেস ডাটাবেসে আমার 10 মিলিয়ন রেকর্ড প্রোগ্রামক্রমে sertোকানো দরকার। বর্তমানে আমি একক "ক্যোয়ারী" -এ 1000 এর সন্নিবেশ বিবৃতিগুলি সম্পাদন করছি।

এটি করার কি আরও ভাল উপায় আছে, কিছু বাল্ক সারণী বিবৃতি যা আমি জানি না?

উত্তর:


211

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


33
আমি স্ট্যাকওভারফ্লো / প্রশ্নগুলি / 12206600/… তেও বিস্তারিত জানাতে আরও কিছু বিশদ লিখেছি ।
ক্রেগ রিঞ্জার

24
); @CraigRinger বাহ, "একটি বিট আরো বিস্তারিত" বেস্ট ন্যূনোক্তি আমি সব সপ্তাহে দেখা যায়
culix

ইনস্টল-প্যাকেজ NpgsqlBulkCopy চেষ্টা করুন
এলিয়র

1
-সিবির সূচীগুলি ডিবি রেকর্ডগুলির শারীরিক বিন্যাসের জন্যও ব্যবহৃত হয়। কোনও ডাটাবেসে সূচি অপসারণ করা ভাল ধারণা কিনা তা নিশ্চিত নন।
ফরজাদ

তবে আপনার প্রস্তাবিত, মেমোরিতে কিছুই নেই !!! এবং যদি আপনার ব্যাচের আকারটি ছোট সংখ্যক হতে পারে তবে এটি খুব শ্রেণীর খারাপ কাজ করেছে :( আমি এনজিপএসকিএলএল কপিআইন ক্লাস চেষ্টা করি, কারণ এটি পিজির ক্যোয়ারী স্টেটমেন্টের সিএসভি ফর্ম্যাট ম্যাপিংয়ের মতো। আপনি বিগ টেবিলের জন্য চেষ্টা করতে পারেন?
এলিয়োর

93

সিপিওয়াই ব্যবহার করার বিকল্প রয়েছে যা পোস্টগ্র্রেস সমর্থন করে এমন মাল্ট্রো মানগুলির বাক্য গঠন। ডকুমেন্টেশন থেকে :

INSERT INTO films (code, title, did, date_prod, kind) VALUES
    ('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'),
    ('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy');

উপরের কোডটি দুটি সারি সন্নিবেশ করানো হয়েছে, তবে যতক্ষণ না আপনি প্রস্তুত বিবৃতি টোকেনের সর্বাধিক সংখ্যক আঘাত না করেন ততক্ষণ আপনি এটিকে নির্বিচারে প্রসারিত করতে পারেন (এটি $ 999 হতে পারে, তবে আমি এটি সম্পর্কে 100% নিশ্চিত নই)। কখনও কখনও কেউ কপি ব্যবহার করতে পারে না, এবং এটি এই পরিস্থিতিতে উপযুক্ত প্রতিস্থাপন।


12
আপনি কি জানেন যে এই পদ্ধতির পারফরম্যান্স কীভাবে তুলনা করে?
অনুদান হামফ্রিজ

আপনি যদি কোনও অনুমতি সমস্যায় পড়ে থাকেন তবে এটি চেষ্টা করার আগে কপি ব্যবহার করুন ... স্টাডিন থেকে
অ্যান্ড্রু স্কট ইভান্স

আপনি যদি সারি-স্তরের সুরক্ষা ব্যবহার করেন তবে এটি আপনার পক্ষে সেরা। সংস্করণ 12 হিসাবে "সারি-স্তরের সুরক্ষা সহ টেবিলগুলির জন্য কপির থেকে সমর্থন করা যায় না"
এলফ

কপি প্রসারিত INSERT এর চেয়ে অনেক দ্রুত
হিপারট্র্যাকার

24

জিনিসের গতি বাড়ানোর একটি উপায় হ'ল স্পষ্টভাবে একাধিক সন্নিবেশ সম্পাদন করা বা কোনও লেনদেনের মধ্যে অনুলিপি করা (1000 বলুন)। পোস্টগ্রিসের ডিফল্ট আচরণটি প্রতিটি বিবৃতি দেওয়ার পরে প্রতিশ্রুতিবদ্ধ হয়, সুতরাং কমিটসকে ব্যাচ করে আপনি কিছুটা ওভারহেড এড়াতে পারেন। ড্যানিয়েলের উত্তরের গাইড যেমনটি বলেছেন, এটি কাজ করার জন্য আপনাকে অটোকোমিট অক্ষম করতে হতে পারে। নীচের অংশে মন্তব্যটি নোট করুন যা ওয়ালে_বাফারগুলির আকার 16 মেগাবাইটে বাড়িয়ে তুলতে সহায়তা করে।


1
এটি উল্লেখ করার মতো যে আপনি একই লেনদেনে কয়টি সন্নিবেশ / অনুলিপি যুক্ত করতে পারবেন তার সীমা আপনার চেষ্টা করা যেকোন কিছু থেকে সম্ভবত অনেক বেশি। আপনি একই লেনদেনের মধ্যে কয়েক মিলিয়ন এবং কয়েক মিলিয়ন সারি যুক্ত করতে পারেন এবং সমস্যার মধ্যে পড়ে না।
সুমিত জৈন

@ সুমিতজাইন হ্যাঁ, আমি প্রতি লেনদেনের অনুলিপি / সন্নিবেশকের সংখ্যার দিক থেকে কেবল 'গতিতে মিষ্টি স্পট' নিয়ে মন্তব্য করছি।
দানা দ্য সনে

লেনদেন চলাকালীন এটি কি টেবিলটি লক করে দেবে?
লাম্বদা পরী

15

UNNESTঅ্যারের সাথে ফাংশনটি মাল্ট্রো ভ্যালু সিনট্যাক্সের পাশাপাশি ব্যবহার করা যেতে পারে। আমি মনে করি যে এই পদ্ধতিটি ব্যবহারের চেয়ে ধীরগতির COPYতবে এটি আমার জন্য সাইকোপজি এবং পাইথন (অজগরটি পিজি হয়ে listগেছে ) নিয়ে কাজ করে:cursor.executeARRAY

INSERT INTO tablename (fieldname1, fieldname2, fieldname3)
VALUES (
    UNNEST(ARRAY[1, 2, 3]), 
    UNNEST(ARRAY[100, 200, 300]), 
    UNNEST(ARRAY['a', 'b', 'c'])
);

VALUESঅতিরিক্ত এক্সটেনশন চেক সহ সাবলেট ব্যবহার না করে:

INSERT INTO tablename (fieldname1, fieldname2, fieldname3)
SELECT * FROM (
    SELECT UNNEST(ARRAY[1, 2, 3]), 
           UNNEST(ARRAY[100, 200, 300]), 
           UNNEST(ARRAY['a', 'b', 'c'])
) AS temptable
WHERE NOT EXISTS (
    SELECT 1 FROM tablename tt
    WHERE tt.fieldname1=temptable.fieldname1
);

বাল্ক আপডেটে একই বাক্য গঠন:

UPDATE tablename
SET fieldname1=temptable.data
FROM (
    SELECT UNNEST(ARRAY[1,2]) AS id,
           UNNEST(ARRAY['a', 'b']) AS data
) AS temptable
WHERE tablename.id=temptable.id;

11

আপনি COPY table TO ... WITH BINARY" টেক্সট এবং সিএসভি ফর্ম্যাটগুলির চেয়ে কিছুটা দ্রুত " ব্যবহার করতে পারেন । আপনার যদি লক্ষ লক্ষ সারি সন্নিবেশ করানোর জন্য থাকে এবং আপনি যদি বাইনারি ডেটাতে স্বাচ্ছন্দ্য বোধ করেন তবেই এটি করুন।

পাইথনের একটি রেসিপি এখানে বাইনারি ইনপুট সহ সাইকোপজি 2 ব্যবহার করছে


9

এটি বেশিরভাগ ডাটাবেজে (অন্যান্য) ক্রিয়াকলাপের উপর নির্ভর করে। এই জাতীয় ক্রিয়াকলাপগুলি কার্যকরভাবে অন্যান্য সেশনের জন্য পুরো ডাটাবেসকে স্থির করে দেয়। আর একটি বিবেচনা হ'ল ডেটামোডেল এবং সীমাবদ্ধতা, ট্রিগার ইত্যাদি উপস্থিতি presence

আমার প্রথম পদ্ধতির সর্বদা: লক্ষ্য টেবিলের অনুরূপ কাঠামো সহ একটি (অস্থায়ী) টেবিল তৈরি করুন (টেবিল tmp তৈরি করুন লক্ষ্য হিসাবে 1 * 0 নির্বাচন করুন), এবং টেম্প টেবিলের মধ্যে ফাইলটি পড়া শুরু করুন। তারপরে আমি যাচাই করা যায় কিনা তা পরীক্ষা করে দেখি: সদৃশ, লক্ষ্যগুলি ইতিমধ্যে বিদ্যমান কীগুলি keys

তারপরে আমি কেবলমাত্র "লক্ষ্য থেকে সন্নিবেশ করান * টিএমপি থেকে" বা অনুরূপ নির্বাচন করুন।

যদি এটি ব্যর্থ হয় বা খুব বেশি সময় নেয় তবে আমি এটিকে বাতিল করে দিই এবং অন্যান্য পদ্ধতিগুলি বিবেচনা করি (অস্থায়ীভাবে সূচি / সীমাবদ্ধতা বাদ দেওয়া ইত্যাদি)



6

আমি কেবল এই সমস্যার মুখোমুখি হয়েছি এবং পোষ্টগ্রিসে বাল্ক আমদানির জন্য সিএসভিএসকিএল ( প্রকাশ ) সুপারিশ করব । একটি বাল্ক সন্নিবেশ সম্পাদন করার জন্য আপনি কেবল createdbএবং তারপর ব্যবহার করতে চান csvsqlযা আপনার ডাটাবেসের সাথে সংযোগ স্থাপন করে এবং সিএসভিগুলির পুরো ফোল্ডারের জন্য পৃথক সারণী তৈরি করে।

$ createdb test 
$ csvsql --db postgresql:///test --insert examples/*.csv

1
সিএসভিএসকিএল-এর জন্য, সোর্স সিএসভিকে যে কোনও সম্ভাব্য বিন্যাস ত্রুটি থেকে পরিষ্কার করার জন্য, এই নির্দেশিকাগুলি অনুসরণ করা ভাল , এখানে
সাল

0

বাহ্যিক ফাইলটি হ'ল সেরা এবং সাধারণ বাল্ক-ডেটা

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

কিছু রূপান্তর সঙ্গে বাল্ক সন্নিবেশ

ইন সংক্ষিপ্তসার ETL অ্যাপ্লিকেশন এবং আহার প্রসেস, আমরা এটা ঢোকাতে আগে ডেটা পরিবর্তন করতে হবে। অস্থায়ী টেবিলটি ডিস্কের জায়গা খায় (এটি প্রচুর পরিমাণে করা হয়) এবং এটি এটি করার দ্রুত উপায় নয়। পোস্টগ্রি বিদেশী-ডেটা মোড়কের (FDW) সেরা পছন্দ।

সিএসভি উদাহরণ । ধরুন tablename (x, y, z)এসকিউএল অন এবং একটি সিএসভি ফাইলের মতো

fieldname1,fieldname2,fieldname3
etc,etc,etc
... million lines ...

আপনি ক্লাসিক এসকিউএল COPYলোড করার জন্য ব্যবহার করতে পারেন ( এটি মূল ডেটা যেমন ) তে tmp_tablenameফিল্টার করা ডেটা এতে sertোকান tablename... তবে, ডিস্কের ব্যবহার এড়াতে সেরা দ্বারা সরাসরি ইনজেক্ট করা ভাল

INSERT INTO tablename (x, y, z)
  SELECT f1(fieldname1), f2(fieldname2), f3(fieldname3) -- the transforms 
  FROM tmp_tablename_fdw
  -- WHERE condictions
;

আপনাকে এফডিডাব্লুয়ের জন্য ডাটাবেস প্রস্তুত tmp_tablename_fdwকরতে হবে, এবং পরিবর্তে স্থির আপনি এটি তৈরি করে এমন কোনও ফাংশন ব্যবহার করতে পারেন :

CREATE EXTENSION file_fdw;
CREATE SERVER import FOREIGN DATA WRAPPER file_fdw;
CREATE FOREIGN TABLE tmp_tablename_fdw(
  ...
) SERVER import OPTIONS ( filename '/tmp/pg_io/file.csv', format 'csv');

JSON উদাহরণ । দুটি ফাইলের একটি সেট, myRawData1.jsonএবং এর মাধ্যমে Ranger_Policies2.jsonইনজেক্ট করা যায়:

INSERT INTO tablename (fname, metadata, content)
 SELECT fname, meta, j  -- do any data transformation here
 FROM jsonb_read_files('myRawData%.json')
 -- WHERE any_condiction_here
;

যেখানে ফাংশন jsonb_read_files () একটি ফোল্ডারের সমস্ত ফাইল পড়ে, যা একটি মুখোশ দ্বারা সংজ্ঞায়িত:

CREATE or replace FUNCTION jsonb_read_files(
  p_flike text, p_fpath text DEFAULT '/tmp/pg_io/'
) RETURNS TABLE (fid int,  fname text, fmeta jsonb, j jsonb) AS $f$
  WITH t AS (
     SELECT (row_number() OVER ())::int id, 
           f as fname,
           p_fpath ||'/'|| f as f
     FROM pg_ls_dir(p_fpath) t(f)
     WHERE    f like p_flike
  ) SELECT id,  fname,
         to_jsonb( pg_stat_file(f) ) || jsonb_build_object('fpath',p_fpath),
         pg_read_file(f)::jsonb
    FROM t
$f$  LANGUAGE SQL IMMUTABLE;

জিজিপ স্ট্রিমিংয়ের অভাব

"ফাইল ইনজেশন" (মূলত বিগ ডেটাতে) জন্য সর্বাধিক ঘন পদ্ধতিটি জিজিপ ফর্ম্যাটে আসল ফাইলটি সংরক্ষণ করে এবং স্ট্রিমিং অ্যালগরিদম দিয়ে এটি স্থানান্তরিত করে যা ইউনিক্স পাইপগুলিতে দ্রুত এবং ডিস্ক ব্যয় ছাড়াই চলতে পারে:

 gunzip remote_or_local_file.csv.gz | convert_to_sql | psql 

সুতরাং আদর্শ (ভবিষ্যত) হ'ল বিন্যাসের জন্য একটি সার্ভার বিকল্প.csv.gz

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