PostgreSQL এ কীভাবে সন্নিবেশ কর্মক্ষমতা বাড়ায়


215

আমি পোস্টগ্রিস সন্নিবেশ সম্পাদনা পরীক্ষা করছি testing আমার কাছে একটি কলামযুক্ত একটি টেবিল রয়েছে যার সংখ্যার ডেটা টাইপ রয়েছে। এটিতে একটি সূচকও রয়েছে। আমি এই ক্যোয়ারীটি ব্যবহার করে ডাটাবেস পূরণ করেছি:

insert into aNumber (id) values (564),(43536),(34560) ...

আমি উপরের ক্যোয়ারী সহ খুব দ্রুত 10,000 টি 4,000 সারি .োকিয়েছি। ডাটাবেস 6 মিলিয়ন সারির কার্য সম্পাদন করার পরে প্রতি 15 মিনিটে 1 মিলিয়ন সারিতে মারাত্মকভাবে হ্রাস পেয়েছে। সন্নিবেশ কর্মক্ষমতা বাড়াতে কোন কৌশল আছে? এই প্রকল্পে আমার সর্বোত্তম সন্নিবেশ কর্মক্ষমতা প্রয়োজন।

5 জিবি র‌্যাম সহ একটি মেশিনে উইন্ডোজ 7 প্রো ব্যবহার করা।


5
প্রশ্নগুলিতেও আপনার পিজি সংস্করণটি উল্লেখ করার মতো। এই ক্ষেত্রে এটি প্রচুর পার্থক্য করে না, তবে এটি অনেক প্রশ্নের জন্যই করে।
ক্রেগ রিঞ্জার

1
টেবিলের উপর সূচকগুলি ফেলে দিন এবং যদি থাকে তবে ট্রিগার করে sertোকান স্ক্রিপ্টটি। একবার আপনি বাল্ক লোড সম্পন্ন করার পরে আপনি সূচিগুলি পুনরায় তৈরি করতে পারেন।
সন্দীপ

উত্তর:


481

দেখুন একটি ডাটাবেস পূরণ পোস্টগ্রি ম্যানুয়াল, depesz এর চমৎকার হিসাবে চলিত নিবন্ধ বিষয়ে, এবং এই তাই প্রশ্ন

(নোট যে এই উত্তরটি একটি বিদ্যমান ডিবি বা একটি নতুন তৈরি ডেটা বাল্ক লোড হচ্ছে সম্পর্কে। তুমি আগ্রহী ডিবি সঙ্গে কর্মক্ষমতা পুনরুদ্ধার যদি pg_restoreবা psqlসঞ্চালনের pg_dumpআউটপুট, অনেক এই যেহেতু প্রযোজ্য নয় pg_dumpএবং pg_restoreইতিমধ্যে তৈরি মত কাজগুলি এটি একটি স্কিমা + ডেটা পুনরুদ্ধার শেষ করার পরে ট্রিগার এবং সূচকগুলি)

অনেক কিছুই করার দরকার আছে। আদর্শ সমাধানটি UNLOGGEDহ'ল সূচি ছাড়াই কোনও টেবিলের মধ্যে আমদানি করা , তারপরে এটি লগতে পরিবর্তন করে সূচিগুলি যুক্ত করা। দুর্ভাগ্যক্রমে PostgreSQL 9.4 এ UNLOGGEDলগ থেকে টেবিল পরিবর্তন করার কোনও সমর্থন নেই । 9.5 যোগALTER TABLE ... SET LOGGED করার অনুমতিতে করে।

আপনি যদি বাল্ক আমদানির জন্য আপনার ডাটাবেস অফলাইনে নিতে পারেন তবে ব্যবহার করুন pg_bulkload

অন্যথায়:

  • টেবিলে কোনও ট্রিগার অক্ষম করুন

  • আমদানি শুরুর আগে সূচকগুলি ফেলে দিন, পরে এগুলি পুনরায় তৈরি করুন। (এটি একই ধরণের ডেটাতে ক্রমবর্ধমানভাবে যুক্ত করার চেয়ে এক পাসে একটি সূচক তৈরি করতে অনেক কম সময় নেয় এবং ফলাফল সূচকটি আরও বেশি কমপ্যাক্ট হয়)।

  • যদি একক লেনদেনের মধ্যে আমদানি করা হয়, তবে বিদেশী কী সীমাবদ্ধতাগুলি ফেলে রাখা, আমদানি করা এবং প্রতিশ্রুতি দেওয়ার আগে সীমাবদ্ধতাগুলি পুনরায় তৈরি করা নিরাপদ। যদি আপনি অবৈধ ডেটা প্রবর্তন করতে পারেন তবে আমদানি একাধিক লেনদেনের মধ্যে বিভক্ত হলে এটি করবেন না।

  • সম্ভব হলে এস এর COPYপরিবর্তে ব্যবহার করুনINSERT

  • আপনি যদি ব্যবহার করতে না পারেন তবে ব্যবহারিক হলে COPYবহু-মূল্যবান ব্যবহার করে বিবেচনা করুন INSERT। আপনি ইতিমধ্যে এটি করছেন বলে মনে হচ্ছে। যদিও এককটিতে অনেকগুলি মান তালিকাবদ্ধ করার চেষ্টা করবেন না VALUES; এই মানগুলি কয়েক বার মেমরির মধ্যে ফিট করতে হয়, তাই প্রতি বিবৃতিতে কয়েকশতে রাখুন।

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

  • Fsync () ব্যয় হ্রাস করতে ব্যবহার করুন synchronous_commit=offএবং একটি বিশাল commit_delay। যদিও আপনি আপনার কাজকে বড় লেনদেনের জন্য সজ্জিত করেছেন তবে এটি খুব বেশি সহায়ক হবে না।

  • INSERTবা COPYবেশ কয়েকটি সংযোগ থেকে সমান্তরালে। আপনার হার্ডওয়ারের ডিস্ক সাবসিস্টেমের উপর কতজন নির্ভর করে; থাম্বের নিয়ম হিসাবে, আপনি সরাসরি সংযুক্ত স্টোরেজ ব্যবহার করে শারীরিক হার্ড ড্রাইভের জন্য একটি সংযোগ চান।

  • একটি উচ্চ checkpoint_segmentsমান সেট করুন এবং সক্ষম করুন log_checkpoints। পোস্টগ্রেএসকিউএল লগগুলি দেখুন এবং নিশ্চিত করুন যে এটি খুব ঘন ঘন ঘটে যাওয়া চেকপয়েন্টগুলি সম্পর্কে অভিযোগ করে না।

  • যদি এবং কেবলমাত্র যদি আপনি আপনার পুরো পোস্টগ্রাইএসকিউএল ক্লাস্টার (আপনার ডাটাবেস এবং একই ক্লাস্টারের অন্য কোনও লোককে) ধ্বংসাত্মক দুর্নীতির জন্য হারিয়ে যাওয়ার আপত্তি না দেখান যদি সিস্টেমটি আমদানির সময় ক্র্যাশ হয়ে যায়, আপনি Pg, সেট fsync=off, পিজি শুরু করতে, আপনার আমদানি করতে, তারপরে (প্রাণবন্ত) Pg বন্ধ করে fsync=onআবার সেট করুন । ওয়াল কনফিগারেশন দেখুন । যদি আপনার পোস্টগ্রিজ এসকিউএল ইনস্টলের কোনও ডাটাবেসে আপনার যত্ন নেওয়া কোনও ডেটা ইতিমধ্যে থাকে তবে এটি করবেন না। আপনি যদি সেট করেন তবে আপনি সেটও fsync=offকরতে পারবেন full_page_writes=off; আবার, ডাটাবেস দুর্নীতি এবং ডেটা ক্ষতি রোধ করতে আপনার আমদানির পরে এটি আবার চালু করার কথা মনে রাখবেন। Pg ম্যানুয়ালটিতে অ-টেকসই সেটিংস দেখুন ।

আপনার সিস্টেমে টিউন করার দিকেও আপনার নজর দেওয়া উচিত:

  • ব্যবহার করুন ভাল মানের যতটা সম্ভব সঞ্চয়ের জন্য SSDs। নির্ভরযোগ্য, শক্তি-সুরক্ষিত লিখিত-ব্যাক ক্যাশেযুক্ত ভাল এসএসডি কমিটের হারকে অবিশ্বাস্যভাবে দ্রুততর করে তোলে। আপনি উপরের পরামর্শগুলি অনুসরণ করলে এগুলি কম উপকারী - যা ডিস্ক ফ্লাশ / fsync()গুলি হ্রাস করে - তবে এখনও বড় সাহায্য হতে পারে। যথাযথ পাওয়ার-ব্যর্থতা সুরক্ষা ব্যতীত সস্তা এসএসডি ব্যবহার করবেন না যদি না আপনি আপনার ডেটা রাখার বিষয়ে চিন্তা করেন।

  • আপনি যদি সরাসরি সংযুক্ত স্টোরেজের জন্য RAID 5 বা RAID 6 ব্যবহার করেন তবে এখনই থামুন। আপনার ডেটা ব্যাক আপ করুন, আপনার RAID অ্যারেটিকে RAID 10 এ পুনর্গঠন করুন এবং আবার চেষ্টা করুন। RAID 5/6 বাল্ক রাইটিং পারফরম্যান্সের জন্য হতাশ - যদিও একটি বড় ক্যাশে সহ একটি ভাল RAID নিয়ামক সাহায্য করতে পারে।

  • আপনার যদি একটি বড় ব্যাটারি ব্যাকযুক্ত লেখার পিছনে ক্যাশে সহ একটি হার্ডওয়্যার RAID নিয়ামক ব্যবহার করার বিকল্প থাকে তবে এটি প্রচুর কমিটের সাহায্যে কাজের চাপের জন্য লেখার কার্যকারিতা উন্নত করতে পারে। যদি আপনি অ্যাসিঙ্ক কমিটকে কমিট_ডিলি ব্যবহার করেন বা বাল্ক লোডিংয়ের সময় আপনি যদি আরও কম বড় লেনদেন করছেন তবে এটি তেমন সুবিধা দেয় না।

  • যদি সম্ভব pg_xlogহয় তবে একটি পৃথক ডিস্ক / ডিস্ক অ্যারেতে ওয়াল ( ) সংরক্ষণ করুন। একই ডিস্কে একটি পৃথক ফাইল সিস্টেম ব্যবহার করার সামান্য বিন্দু আছে। লোকেরা প্রায়শই ওয়াল এর জন্য একটি RAID1 জোড়া ব্যবহার করতে পছন্দ করে। আবার উচ্চ প্রতিশ্রুতিবদ্ধ হারের সিস্টেমে এটির আরও বেশি প্রভাব পড়ে এবং আপনি যদি কোনও লোড লোড লক্ষ্য হিসাবে একটি আনলগড টেবিল ব্যবহার করেন তবে এর খুব কম প্রভাব পড়ে।

আপনি দ্রুত পরীক্ষার জন্য পোস্টগ্রের এসকিউএল অনুকূল করতে আগ্রহী হতে পারেন ।


1
আপনি কি সম্মত হবেন যে ভাল মানের এসএসডি ব্যবহার করা হলে RAID 5/6 থেকে রাইটিং পেনাল্টি কিছুটা হ্রাস করা যায়? স্পষ্টতই এখনও একটি জরিমানা রয়েছে, তবে আমি মনে করি পার্থক্যটি এইচডিডিগুলির তুলনায় অনেক কম বেদনাদায়ক।

1
আমি এটা পরীক্ষা করিনি। আমি বলব এটি সম্ভবত কম খারাপ - দুষ্টু লেখার প্রশস্তকরণ প্রভাব এবং (ছোট লেখকদের জন্য) একটি পঠন-সংশোধন-লেখার চক্রের প্রয়োজন এখনও রয়েছে, তবে অতিরিক্ত অনুসন্ধানের জন্য কঠোর শাস্তি হওয়া উচিত নয়।
ক্রেগ রিঞ্জার

আমরা কি কেবল সূচকগুলি বাদ দেওয়ার পরিবর্তে অক্ষম করতে পারি, উদাহরণস্বরূপ, indisvalid( postgresql.org/docs/8.3/static/catolog-pg-index.html ) সেট করে মিথ্যা, তারপরে ডেটা লোড করুন এবং তারপরে অনলাইনে সূচি আনতে পারেন REINDEX?
ভ্লাদিস্লাভ রাস্ট্রুসনি

1
@ ক্রেইগ্রিঞ্জার এসএসডি এর সাথে পার্ক এইচ 30৩০-তে RAID-5 বনাম RAID-10 পরীক্ষা করেছি। RAID-5 আসলে দ্রুত হয়। এছাড়াও এটি লক্ষনীয় হতে পারে যে বড় বাইটিয়ার সাথে সংযুক্ত করে সন্নিবেশ / লেনদেনগুলি অনুলিপিটির চেয়ে দ্রুত বলে মনে হয়। সামগ্রিকভাবে ভাল পরামর্শ যদিও।
অ্যাটলাস্ট

2
কেউ কি বড় গতির উন্নতি দেখতে পাচ্ছেন UNLOGGED? একটি দ্রুত পরীক্ষা 10-20% উন্নতির মতো কিছু দেখায়।
সার্গ

15

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

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


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

11

দুর্দান্ত ক্রেইগ রিঞ্জার পোস্ট এবং ডিপিজের ব্লগ পোস্টের পাশাপাশি আপনি যদি কোনও লেনদেনের অভ্যন্তরে রেডি -স্টেটমেন্ট সন্নিবেশ ব্যবহার করে ওডিবিসি ( পিএসকিলোডবিসি ) ইন্টারফেসের মাধ্যমে আপনার সন্নিবেশগুলি দ্রুত করতে চান তবে এটি তৈরি করতে আপনার আরও কিছু অতিরিক্ত জিনিস করতে হবে দ্রুত কাজ:

  1. Protocol=-1সংযোগের স্ট্রিংয়ে উল্লেখ করে "লেনদেন" -র-রোলব্যাক-অন-ত্রুটিগুলি সেট করুন । ডিফল্টরূপে পিএসকিলোডবিসি "স্টেটমেন্ট" স্তর ব্যবহার করে, যা সম্পূর্ণ বিবরণীর পরিবর্তে প্রতিটি বিবরণের জন্য একটি SAVEPOINT তৈরি করে, সন্নিবেশকে ধীর করে দেয়।
  2. UseServerSidePrepare=1সংযোগ স্ট্রিংয়ে উল্লেখ করে সার্ভার-সাইড প্রস্তুত বিবৃতি ব্যবহার করুন । এই বিকল্পটি ছাড়াই ক্লায়েন্ট প্রতিটি সারি সন্নিবেশ করার সাথে সাথে পুরো সন্নিবেশ বিবৃতি প্রেরণ করে।
  3. প্রতিটি বিবৃতি ব্যবহার করে স্ব-প্রতিশ্রুতি অক্ষম করুন SQLSetConnectAttr(conn, SQL_ATTR_AUTOCOMMIT, reinterpret_cast<SQLPOINTER>(SQL_AUTOCOMMIT_OFF), 0);
  4. সমস্ত সারি owsোকানো হয়ে গেলে ব্যবহার করে লেনদেনটি কমিট করুন SQLEndTran(SQL_HANDLE_DBC, conn, SQL_COMMIT);। স্পষ্টভাবে কোনও লেনদেন খোলার দরকার নেই।

দুর্ভাগ্যক্রমে, পিএসকিলোডবিসি SQLBulkOperationsঅপ্রস্তুত সন্নিবেশ বিবৃতিগুলির একটি সিরিজ জারি করে "প্রয়োগ" করে, যাতে দ্রুততম সন্নিবেশ অর্জন করার জন্য কোনও ব্যক্তিকে উপরের পদক্ষেপগুলিতে ম্যানুয়ালি কোড আপ করতে হবে।


A8=30000000সংযোগের স্ট্রিংয়ের মধ্যে বৃহত সকেট বাফার আকার সন্নিবেশগুলিকে গতি বাড়ানোর জন্যও ব্যবহার করা উচিত।
আন্দ্রেস

9

আমি আজ একই ইস্যুতে প্রায় 6 ঘন্টা ব্যয় করেছি। সন্নিবেশগুলি 5MI (মোট 30MI এর বাইরে) সারি পর্যন্ত একটি 'নিয়মিত' গতিতে (100 কে প্রতি 3 সেকেন্ডের কম) গতিতে চলে যায় এবং তারপরে পারফরম্যান্স মারাত্মকভাবে ডুবে যায় (সমস্তভাবে 100 কে প্রতি 1 মিনিটে নেমে যায়)।

আমি যে সমস্ত কাজ করে না এবং সরাসরি মাংসে কাটেনি সেগুলি আমি তালিকাই দেব না।

আমি টার্গেট টেবিলে একটি প্রাথমিক কী ফেলেছি (যা একটি জিইউইডি ছিল) এবং আমার 30 এমআই বা সারিগুলি সুখে 100K প্রতি 3 সেকেন্ডেরও কম গতিতে গন্তব্যে প্রবাহিত হয়েছিল।


6

আপনি যদি ইউইউডিএস (যা আপনার ক্ষেত্রে ঠিক তেমন নয় ) দিয়ে কলম toোকানো এবং @ ডেনিস উত্তরটি যোগ করতে (তবে আমি এখনও কোনও মন্তব্য করতে পারি না) জেন_রাডম_উইইড () পিজি 9.4 এবং পিজক্রিপ্টো মডিউল প্রয়োজন) এর চেয়ে পরামর্শ দিন (একটি uuid_generate_v4 এর চেয়ে অনেক বেশি)

=# explain analyze select uuid_generate_v4(),* from generate_series(1,10000);
                                                        QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------
 Function Scan on generate_series  (cost=0.00..12.50 rows=1000 width=4) (actual time=11.674..10304.959 rows=10000 loops=1)
 Planning time: 0.157 ms
 Execution time: 13353.098 ms
(3 filas)

বনাম


=# explain analyze select gen_random_uuid(),* from generate_series(1,10000);
                                                        QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------
 Function Scan on generate_series  (cost=0.00..12.50 rows=1000 width=4) (actual time=252.274..418.137 rows=10000 loops=1)
 Planning time: 0.064 ms
 Execution time: 503.818 ms
(3 filas)

এছাড়াও এটি করার পরামর্শ দেওয়া সরকারী উপায়

বিঃদ্রঃ

আপনার যদি কেবল এলোমেলোভাবে উত্পাদিত (সংস্করণ 4) ইউআইডিগুলির প্রয়োজন হয় তবে পরিবর্তে পিজক্রিপ্টো মডিউল থেকে জেন_রেন্ডম_ইউইড () ফাংশনটি ব্যবহার করার বিষয়টি বিবেচনা করুন।

এটি সারিগুলির 7.7 এম এর জন্য sert 2 ঘন্টা থেকে 10 মিনিটের মধ্যে সন্নিবেশের সময়টি ফেলেছে।


1

অনুকূল সন্নিবেশ কর্মক্ষমতা জন্য সূচকটি অক্ষম করুন যদি এটি আপনার জন্য একটি বিকল্প। এর বাইরে আরও ভাল হার্ডওয়্যার (ডিস্ক, মেমরি) সহায়ক


-1

আমি এই সন্নিবেশ কর্মক্ষমতা সমস্যারও মুখোমুখি হয়েছি। আমার সমাধান সন্নিবেশ কাজ শেষ করতে কিছু গো রুটিন স্প্যান হয়। ইতিমধ্যে, SetMaxOpenConnsএকটি সঠিক নম্বর দেওয়া উচিত অন্যথায় অনেকগুলি ওপেন সংযোগ ত্রুটি সতর্ক করা হবে।

db, _ := sql.open() 
db.SetMaxOpenConns(SOME CONFIG INTEGER NUMBER) 
var wg sync.WaitGroup
for _, query := range queries {
    wg.Add(1)
    go func(msg string) {
        defer wg.Done()
        _, err := db.Exec(msg)
        if err != nil {
            fmt.Println(err)
        }
    }(query)
}
wg.Wait()

আমার প্রকল্পের জন্য লোডিং গতি অনেক দ্রুত। এই কোড স্নিপেটটি কীভাবে এটি কাজ করে তা একটি ধারণা দিয়েছে। পাঠকদের সহজেই এটি পরিবর্তন করতে সক্ষম হওয়া উচিত।


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