it-swarm.asia

بطء سرعة تحميل البيانات من mysqldump

لقد حصلت على قاعدة بيانات MySQL متوسطة الحجم مع حوالي 30 جدولًا ، بعضها 10 ملايين سجل ، وحوالي 100 مليون. mysqldump لجميع الجداول (في ملفات منفصلة) سريع إلى حد ما ، ربما يستغرق 20 دقيقة. يولد حوالي 15 جيجابايت من البيانات. أكبر الملفات التي تم تفريغها تقع في نطاق 2 جيجابايت.

عندما أقوم بتحميل البيانات في MySQL في صندوق آخر ، وهو جهاز سداسي النواة ، سعة 8 جيجا بايت ، فإنه يستغرق إلى الأبد. بسهولة 12 ساعة ساعة أو أكثر.

أنا فقط أقوم بتشغيل عميل الخلية لتحميل الملف ، أي.

mysql database < footable.sql

مباشرة مع الملف مباشرة من mysqldump

mysqldump database foo > footable.sql

من الواضح أنني أفعل شيئًا خاطئًا. من أين أبدأ حتى تنتهي في وقت معقول؟

أنا لا أستخدم أي مفاتيح تشغيل إما على التفريغ أو الحمل.

21
Pat Farrell

خذ هذه النقاط في اعتبارك أنها قد تساعدك في حالة إنشاء التفريغ واستعادته.

  1. استعمال Extended inserts في مقالب.
  2. تفريغ مع --tab التنسيق حتى تتمكن من استخدام mysqlimport وهو أسرع من mysql < dumpfile.
  3. استيراد بخيوط متعددة ، واحد لكل جدول.
  4. استخدم محرك قاعدة بيانات مختلف إذا أمكن. يعد الاستيراد إلى محرك معاملات كثيف مثل innodb بطيئًا للغاية. يعد الإدخال إلى محرك غير معاملات مثل MyISAM أسرع بكثير.
  5. أوقف عمليات فحص المفاتيح الخارجية وشغّل الالتزام التلقائي.
  6. إذا كنت تقوم بالاستيراد إلى Innodb ، فإن أكثر ما يمكنك فعله هو وضع innodb_flush_log_at_trx_commit = 2 في my.cnf ، مؤقتًا أثناء تشغيل الاستيراد. يمكنك إعادته إلى 1 إذا كنت بحاجة إلى ACID

جربها..

22
Abdul Manaf

لقد تعاملت كثيرًا مع هذا مؤخرًا. يمكنك بالتأكيد تحسين أداء الاستيراد عن طريق إجراء عمليات الاستيراد بالتوازي. يعتمد معظم التباطؤ على الإدخال/الإخراج ، ولكن لا يزال بإمكانك الحصول على تحسين بنسبة 40٪ عن طريق الإغراق في الجداول ثم استيرادها على سبيل المثال 4 في المرة الواحدة.

يمكنك القيام بذلك باستخدام xargs مثل هذا:

ls *.sql -1c | xargs -P4 -I tbl_name sh -c "mysql --user=username --password database < tbl_name"

إن وجود الملفات مضغوطة قبل دفعها إلى mysql لا يبطئ أي شيء في الغالب بسبب انخفاض الإدخال/الإخراج. تم ضغط طاولاتي حتى حوالي 10: 1 ، مما يوفر الكثير من مساحة القرص.

لقد وجدت أنه على 4 أجهزة أساسية ، فإن استخدام 4 عمليات هو الأفضل ، على الرغم من أنه أفضل بشكل هامشي فقط من استخدام 3. إذا كان لديك SSDs أو RAID سريعًا ، فمن المرجح أن تكون أفضل.

بعض الأشياء الأخرى لملاحظة. إذا كان لديك محركات أقراص قطاع 4K ، فتأكد من أن لديك key_cache_block_size=4096 و myisam_block_size=4K.

إذا كنت تستخدم جداول MyISAM ، قم بتعيين myisam_repair_threads = 2 أو أعلى. سيسمح ذلك للنوى الإضافية للمساعدة في إعادة بناء الفهارس.

تأكد من عدم المبادلة على الإطلاق. إذا كنت تخفض حجم innodb_buffer_pool_size.

أعتقد أنني حصلت على بعض التسارع مع innnodb من خلال هذه الخيارات أيضًا:

innodb_flush_method= O_DIRECT (LINUX ONLY)
innodb_flush_log_at_commit = 0
innodb_doublewrite=0
innodb_support_xa=0
innodb_checksums=0

(الثلاثة الأخيرة التي لم أختبرها على نطاق واسع - أعتقد أنني وجدتها كاقتراحات على الإنترنت). لاحظ أن innodb_flush_log_at_commit=0 يمكن أن يؤدي إلى الفساد مع انهيار الخلية أو انقطاع التيار الكهربائي.

7
greg

بالإضافة إلى عبد إجابة أود التأكيد على أهمية --disable-keys الخيار ، الذي يوقف تشغيل المفاتيح حتى يتم تحميل جميع البيانات للجدول. يتم تمكين هذا الخيار كجزء من --opt تبديل ، والذي يتم تمكينه افتراضيًا ، ولكنه يعتقد أنه من المهم الإشارة إليه.

إذا لم تقم بتخطي المفاتيح أثناء الإدخالات ، فإن كل صف مدرج سيعيد بناء الفهرس. عملية بطيئة للغاية.

7
Derek Downey

إذا كان لديك بشكل رئيسي جداول MyISAM ، يجب عليك زيادة المخزن المؤقت للإدراج المجمع . إليك ما تقوله وثائق MySQL عن إعداد bulk_insert_buffer_size :

يستخدم MyISAM ذاكرة تخزين مؤقت خاصة تشبه الشجرة لإجراء إدخالات مجمعة بشكل أسرع لـ INSERT ... SELECT و INSERT ... VALUES (...) و (...) و ... و LOAD DATA INFILE عند إضافة البيانات إلى غير فارغة الجداول. يحدد هذا المتغير حجم شجرة التخزين المؤقت بالبايت لكل مؤشر ترابط. يؤدي تعيينه إلى 0 إلى تعطيل هذا التحسين. القيمة الافتراضية هي 8 ميغابايت.

هناك شيئين عليك القيام به

1) أضفه إلى /etc/my.cnf

[mysqld]
bulk_insert_buffer_size=512M

2) حدد القيمة العالمية لذلك

SET GLOBAL bulk_insert_buffer_size = 1024 * 1024 * 512;

إذا لم يكن لديك امتياز لتعيين حجم_الملفات_جملة_على مستوى العالم ، فقم بذلك

service mysql restart

بالطبع ، هذا ليس لـ InnoDB.

من زاوية أخرى ، سواء كانت الجداول InnoDB أو MyISAM ، إذا كانت الفهارس أكبر من الجدول ، فقد يكون لديك الكثير من الفهارس. أنا عادة أضيف أن إعادة تحميل MyISAM mysqldump يجب أن يستغرق 3 مرات طالما استغرق mysqldump. كما أنني أضمن أن إعادة تحميل mysqldump من InnoDB يجب أن يستغرق 4 مرات طالما استغرق mysqldump القيام به.

إذا كنت تتجاوز نسبة 4: 1 لإعادة تحميل mysqldump ، فأنت بالتأكيد تواجه مشكلة من مشكلتين:

  • الكثير من الفهارس
  • فهارس كبيرة فقط بسبب الأعمدة الكبيرة

يمكنك قياس حجم البيانات الخاصة بك عن طريق محرك التخزين مع ما يلي:

SELECT IFNULL(B.engine,'Total') "Storage Engine",
CONCAT(LPAD(REPLACE(FORMAT(B.DSize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Data Size", CONCAT(LPAD(REPLACE(
FORMAT(B.ISize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Index Size", CONCAT(LPAD(REPLACE(
FORMAT(B.TSize/POWER(1024,pw),3),',',''),17,' '),' ',
SUBSTR(' KMGTP',pw+1,1),'B') "Table Size" FROM
(SELECT engine,SUM(data_length) DSize,SUM(index_length) ISize,
SUM(data_length+index_length) TSize FROM
information_schema.tables WHERE table_schema NOT IN
('mysql','information_schema','performance_schema') AND
engine IS NOT NULL GROUP BY engine WITH ROLLUP) B,
(SELECT 3 pw) A ORDER BY TSize;

تحقق مما إذا كانت الفهارس تقريبًا بحجم البيانات أم أكبر

قد تفكر أيضًا في تعطيل التسجيل الثنائي مثل هذا:

echo "SET SQL_LOG_BIN=0;" > footable.sql
mysqldump --databases foo >> footable.sql

قبل إعادة تحميل البرنامج النصي

5
RolandoMySQLDBA

إذا تجاوزت نظام الملفات تمامًا وقمت فقط بتوجيه إخراج mysqldump مباشرة في عملية MySQL ، فمن المفترض أن ترى تحسينات ملحوظة في الأداء. يعتمد المقدار النهائي على نوع محرك الأقراص الذي تستخدمه ولكني نادرًا ما أستخدم ملفات التفريغ بعد الآن بغض النظر عن حجم قاعدة البيانات لهذا السبب وحده.

mysqldump -uxxx -pxxx -hxxx --single-transaction --routines --databases dbname | mysql -uyyy -pyyy -hyyy
2
Marcus Pope

وفقا لتجاربي ، فإن القرص الصلب هو عنق الزجاجة. ننسى أقراص الغزل. SSD هو الأفضل ، ولكن الأفضل بكثير هو القيام بذلك في RAM - إذا كان لديك ما يكفي للاحتفاظ بقاعدة البيانات بأكملها لفترة قصيرة.

  1. توقف الخلية
  2. نقل المحتويات الموجودة لـ/var/lib/mysql
  3. قم بإنشاء فارغ/var/lib/mysql dir
  4. mount -t tmpfs -o size = 32g tmpfs/var/lib/mysql (ضبط الحجم)
  5. إنشاء قاعدة بيانات فارغة (مثل mysql_install_db أو استعادة المحتويات السابقة)
  6. بدء الخلية
  7. استيراد
  8. توقف الخلية
  9. نسخ/فار/ليب/الخلية إلى mysql2
  10. الخلية مايكل. رميدير الخلية
  11. تحريك الخلية إلى الخلية
  12. ابدأ الخلية ، كن سعيدا

بالنسبة لي ، يمكن استيراد تفريغ ~ 10G (/ var/lib/mysql يستهلك ~ 20G) في حوالي 35 دقيقة (mydumper/myloader) ، 45 دقيقة (mysqldump --tab/mysqlimport) ، 50 دقيقة (mysqldump/mysql) ، على Xeon 2x6-core 3.2GHz Xeon.

إذا لم يكن لديك ما يكفي RAM في جهاز واحد ، ولكن لديك العديد من أجهزة الكمبيوتر المجاورة لبعضها البعض مع شبكة سريعة ، سيكون من المثير للاهتمام معرفة ما إذا كان يمكن ربط RAMs مع nbd (شبكة حظر الجهاز). أو ، مع innodb_file_per_table ، ربما يمكنك تكرار العملية المذكورة أعلاه لكل جدول.

1
egmont