Mysql
 sql >> база данни >  >> RDS >> Mysql

Вмъкването на MySql в заявката за избор е твърде бавно за копиране на 100 милиона реда

Всеки INSERT ... SELECT ... заявката придобива СПОДЕЛЕНО заключване на редовете, които чете от изходната таблица в SELECT. Но чрез обработка на по-малки парчета редове, заключването не трае твърде дълго.

Заявката с LIMIT ... OFFSET ще става все по-бавно и по-бавно, докато преминавате през таблицата с източник. При 10 000 реда на парче трябва да изпълните тази заявка 10 000 пъти, като всяка трябва да започне отначало и да сканира таблицата, за да достигне до новото ОТМЕСТВАНЕ.

Без значение какво правите, копирането на 100 милиона реда ще отнеме известно време. Върши много работа.

Бих използвал pt-archiver , безплатен инструмент, предназначен за тази цел. Той обработва редовете на "късове" (или подмножества). Той динамично ще регулира размера на парчетата, така че всяка част да отнема 0,5 секунди.

Най-голямата разлика между вашия метод и pt-archiver е, че pt-archiver не използва LIMIT ... OFFSET , той се разхожда по индекса на първичния ключ, избирайки парчета ред по стойност вместо по позиция. Така всяка част се чете по-ефективно.

Отново вашия коментар:

Очаквам, че намаляването на размера на партидата — и увеличаването на броя на повторенията — ще направи проблема с производителността по-лош , не по-добре.

Причината е, че когато използвате LIMIT с OFFSET , всяка заявка трябва да започне отначало в началото на таблицата и да брои редовете до OFFSET стойност. Това става по-дълго и по-дълго, докато преглеждате таблицата.

Изпълняване на 20 000 скъпи заявки с помощта на OFFSET ще отнеме повече време от изпълнението на 10 000 подобни заявки. Най-скъпата част няма да бъде четене на 5 000 или 10 000 реда или вмъкването им в таблицата на местоназначението. Скъпата част ще прескача около 50 000 000 реда, отново и отново.

Вместо това трябва да преглеждате таблицата по стойности не чрез измествания.

INSERT IGNORE INTO Table2(id, field2, field3)
        SELECT f1, f2, f3
        FROM Table1
        WHERE id BETWEEN rowOffset AND rowOffset+limitSize;

Преди цикъла потърсете MIN(id) и MAX(id) и стартирайте rowOffset на минималната стойност и завъртете до максималната стойност.

Това е начинът, по който работи pt-архиваторът.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как мога да съпоставя дата на Java с DATETIME в mysql (по подразбиране това е TIMESTAMP) с анотации за хибернация

  2. mysql заявка за избор на всички освен нещо

  3. Как да покажа изображение от база данни с помощта на php

  4. Мога ли да разчитам на израза using за затваряне на MySQL връзките?

  5. Незаконен микс от съпоставяния за операция за сравнение дата/час