Nano Hash - криптовалюты, майнинг, программирование

Как улучшить производительность INSERT в очень большой таблице MySQL

Я работаю над большой базой данных MySQL, и мне нужно улучшить производительность INSERT для конкретной таблицы. Он содержит около 200 миллионов строк и имеет следующую структуру:

(небольшая предпосылка: я не эксперт по базам данных, поэтому код, который я написал, может быть основан на неправильных основах. Пожалуйста, помогите мне понять мои ошибки :))

CREATE TABLE IF NOT EXISTS items (
    id INT NOT NULL AUTO_INCREMENT,
    name VARCHAR(200) NOT NULL,
    key VARCHAR(10) NOT NULL,
    busy TINYINT(1) NOT NULL DEFAULT 1,
    created_at DATETIME NOT NULL,
    updated_at DATETIME NOT NULL,

    PRIMARY KEY (id, name),
    UNIQUE KEY name_key_unique_key (name, key),
    INDEX name_index (name)
) ENGINE=MyISAM
PARTITION BY LINEAR KEY(name)
PARTITIONS 25;

Каждый день я получаю много файлов csv, в которых каждая строка состоит из пары «имя; ключ», поэтому мне приходится анализировать эти файлы (добавляя значения created_at и updated_at для каждой строки) и вставлять значения в мою таблицу. В этом случае комбинация «имя» и «ключ» ДОЛЖНА БЫТЬ УНИКАЛЬНОЙ, поэтому я реализовал процедуру вставки следующим образом:

CREATE TEMPORARY TABLE temp_items (
    id INT NOT NULL AUTO_INCREMENT,
    name VARCHAR(200) NOT NULL, 
    key VARCHAR(10) NOT NULL, 
    busy TINYINT(1) NOT NULL DEFAULT 1,  
    created_at DATETIME NOT NULL, 
    updated_at DATETIME NOT NULL,  
    PRIMARY KEY (id) 
    ) 
ENGINE=MyISAM;

LOAD DATA LOCAL INFILE 'file_to_process.csv' 
INTO TABLE temp_items
FIELDS TERMINATED BY ',' 
OPTIONALLY ENCLOSED BY '\"' 
(name, key, created_at, updated_at); 

INSERT INTO items (name, key, busy, created_at, updated_at) 
(
    SELECT temp_items.name, temp_items.key, temp_items.busy, temp_items.created_at, temp_items.updated_at 
    FROM temp_items
) 
ON DUPLICATE KEY UPDATE busy=1, updated_at=NOW();

DROP TEMPORARY TABLE temp_items;

Только что показанный код позволяет мне достичь моей цели, но для завершения его выполнения требуется около 48 часов, и это проблема. Я думаю, что эта низкая производительность вызвана тем, что скрипт должен проверять очень большую таблицу (200 миллионов строк) и для каждой вставки, что пара "имя; ключ" уникальна.

Как я могу улучшить производительность моего скрипта?

Спасибо всем заранее.


Ответы:


1

Вы можете использовать следующие методы для ускорения вставки:

  1. Если вы одновременно вставляете много строк из одного и того же клиента, используйте операторы INSERT с несколькими списками VALUES, чтобы вставлять несколько строк одновременно. Это значительно быстрее (в некоторых случаях во много раз быстрее), чем использование отдельных однострочных операторов INSERT. Если вы добавляете данные в непустую таблицу, вы можете настроить переменную bulk_insert_buffer_size, чтобы сделать вставку данных еще быстрее.

  2. При загрузке таблицы из текстового файла используйте LOAD DATA INFILE. Обычно это в 20 раз быстрее, чем использование инструкций INSERT.

  3. Воспользуйтесь тем фактом, что столбцы имеют значения по умолчанию. Вставляйте значения явно, только если вставляемое значение отличается от значения по умолчанию. Это уменьшает синтаксический анализ, который должен выполнять MySQL, и повышает скорость вставки.

Ссылка: MySQL.com: 8.2.4.1 Оптимизация операторов INSERT

23.07.2016

2

Ваш линейный ключ по имени и большие индексы замедляют работу.

LINEAR KEY необходимо вычислять при каждой вставке. http://dev.mysql.com/doc/refman/5.1/en/partitioning-linear-hash.html

Можете ли вы показать нам некоторые примеры данных file_to_process.csv, возможно, следует построить лучшую схему.

Редактировать посмотрел внимательнее

INSERT INTO items (name, key, busy, created_at, updated_at) 
(
    SELECT temp_items.name, temp_items.key, temp_items.busy, temp_items.created_at, temp_items.updated_at 
    FROM temp_items
) 

это, вероятно, создаст временную таблицу диска, это очень-очень медленно, поэтому вам не следует использовать ее для повышения производительности, или, возможно, вам следует проверить некоторые настройки конфигурации mysql, такие как tmp-table-size и max-heap-table-size, возможно, эти настроены неправильно.

11.08.2013


4

Думая в Java;

  • Разделите список объектов на разделы и сгенерируйте оператор пакетной вставки для каждого раздела.
  • Эффективно используйте ядра ЦП и доступные соединения с базой данных, новые полезные функции Java могут помочь легко достичь параллелизма (например, paralel, forkjoin), или вы можете создать собственный пул потоков, оптимизированный с учетом количества ядер ЦП, которые у вас есть, и направлять потоки из централизованной очереди блокировки в для вызова подготовленных операторов пакетной вставки.
  • Если возможно, уменьшите количество индексов в целевой таблице. Если внешний ключ на самом деле не нужен, просто отбросьте его. Меньше индексов быстрее вставляет.
  • Избегайте использования Hibernate, кроме операций CRUD, всегда пишите SQL для сложных выборок.
  • Уменьшите количество соединений в вашем запросе, вместо того, чтобы заставлять БД использовать потоки Java для фильтрации, агрегирования и преобразования.
  • Если вы чувствуете, что вам не нужно этого делать, не объединяйте выборку и вставку в один оператор sql.
  • Добавьте rewriteBatchedStatements=true в свою строку JDBC, это поможет уменьшить связь на уровне TCP между приложением и БД.
  • Используйте @Transactional для методов, которые выполняют пакетную вставку и сами пишут методы отката.
17.05.2021

5

Вы могли бы использовать

load data local infile ''
REPLACE
into table 

и т.д...

REPLACE гарантирует, что любое повторяющееся значение будет перезаписано новыми значениями. Добавьте SET updated_at=now() в конце, и все готово.

Нет необходимости во временной таблице.

13.05.2014
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..