ЗАГРУЗИТЬ ДАННЫЕ ИЗ S3 - Самый быстрый способ для больших данных и индексов

У меня есть таблица с праздничными предложениями, поэтому, чтобы дать вам представление, каждая строка будет содержать следующие биты данных:

Departure airport
Arrival airport
Start date
Duration
Hotel destination
Resort
Hotel name
Hotel rating
A few tiny integer columns for 1s and 0s.
Price
Date time the row was updated

Теперь все эти предложения упаковываются из 3 таблиц, это flights, accommodation и transfers, упаковка заключается в том, чтобы найти самую дешевую сделку для каждого варианта, такого как аэропорт вылета, продолжительность, основание и т. д.

Таблица, в которую я импортирую, будет состоять примерно из 50 миллионов строк, импорт выполняется очень медленно.

Я удалил индексы, что имело огромное значение, но теперь, когда я повторно добавляю индексы обратно в таблицу после того, как все данные там находятся, это занимает вечность.

Я хотел бы знать, есть ли способ быстрой массовой загрузки данных или есть более быстрый способ добавления индексов обратно в таблицу после добавления данных?

Создать таблицу

`` ''

    CREATE TABLE `iv_deals` (
    `aid` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'Deal Autonumber PK',
    `startdate` DATE NULL DEFAULT NULL COMMENT 'Holiday Start Date',
    `startdatet` TINYINT(2) NOT NULL DEFAULT '0',
    `depairport` CHAR(3) NULL DEFAULT NULL COMMENT 'Departure Airport IATA Code',
    `arrairport` CHAR(3) NULL DEFAULT NULL COMMENT 'Arrival Airport IATA Code',
    `destination` VARCHAR(30) NULL DEFAULT NULL COMMENT 'Holiday Destination',
    `resort` VARCHAR(30) NULL DEFAULT NULL COMMENT 'Holiday Resort',
    `hotel` VARCHAR(50) NULL DEFAULT NULL COMMENT 'Holiday Property Name',
    `iv_PropertyID` INT(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Holiday Property ID',
    `rating` VARCHAR(2) NULL DEFAULT NULL COMMENT 'Holiday Property Star Rating',
    `board` VARCHAR(10) NULL DEFAULT NULL COMMENT 'Holiday Meal Option',
    `duration` TINYINT(2) UNSIGNED NULL DEFAULT '0' COMMENT 'Holiday Duration',
    `2for1` TINYINT(1) UNSIGNED NULL DEFAULT '0' COMMENT 'Is 2nd Week FREE Offer, 0 = False, 1 = True',
    `3for2` TINYINT(1) UNSIGNED NULL DEFAULT '0' COMMENT 'Is 3rd Week FREE Offer, 0 = False, 1 = True',
    `3and4` TINYINT(1) UNSIGNED NULL DEFAULT '0' COMMENT 'Is 3rd and 4th Week FREE Offer, 0 = False, 1 = True',
    `4for3` TINYINT(1) UNSIGNED NULL DEFAULT '0' COMMENT 'Is 4th Week FREE Offer, 0 = False, 1 = True',
    `freebb` VARCHAR(2) NULL DEFAULT NULL COMMENT 'Free Week Meal Option',
    `adults` TINYINT(1) UNSIGNED NULL DEFAULT '0' COMMENT 'Number of Adults',
    `children` TINYINT(1) UNSIGNED NULL DEFAULT '0' COMMENT 'Number of Children',
    `infants` TINYINT(1) UNSIGNED NULL DEFAULT '0' COMMENT 'Number of Infants',
    `price` SMALLINT(4) UNSIGNED NULL DEFAULT '9999' COMMENT 'Price',
    `carrier` VARCHAR(40) NULL DEFAULT NULL COMMENT 'Flight Carrier IATA Code',
    `DateUpdated` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`aid`, `startdatet`),
    UNIQUE INDEX `Unique` (`startdate`, `depairport`, `arrairport`, `iv_PropertyID`, `board`, `duration`, `adults`, `children`, `startdatet`),
    INDEX `ik_Price` (`price`),
    INDEX `ik_Destination` (`destination`),
    INDEX `ik_Resort` (`resort`),
    INDEX `ik_DepAirport` (`depairport`),
    INDEX `ik_Startdate` (`startdate`),
    INDEX `ik_Board` (`board`),
    INDEX `ik_FILTER_ALL` (`price`, `depairport`, `destination`, `resort`, `board`, `startdate`),
    INDEX `iv_PropertyID` (`iv_PropertyID`),
    INDEX `ik_Duration` (`duration`),
    INDEX `rating` (`rating`),
    INDEX `adults` (`adults`),
    INDEX `DirectFromPrice` (`iv_PropertyID`, `depairport`, `arrairport`, `board`, `duration`, `adults`, `children`, `startdate`),
    INDEX `DirectFromPrice_wo_depairport` (`iv_PropertyID`, `arrairport`, `board`, `duration`, `adults`, `children`),
    INDEX `DirectFromPrice_w_pid_dep` (`iv_PropertyID`, `depairport`, `adults`, `children`, `price`),
    INDEX `DirectFromPrice_w_pid_night` (`iv_PropertyID`, `duration`, `adults`, `children`),
    INDEX `DirectFromPrice_Dur_Board` (`iv_PropertyID`, `duration`, `board`, `adults`, `children`),
    INDEX `join_index` (`destination`, `startdate`, `duration`)
)
COLLATE='utf8_general_ci'
AUTO_INCREMENT=1258378560
/*!50100 PARTITION BY LIST (startdatet)
(PARTITION part0 VALUES IN (1) ENGINE = InnoDB,
 PARTITION part1 VALUES IN (2) ENGINE = InnoDB,
 PARTITION part2 VALUES IN (3) ENGINE = InnoDB,
 PARTITION part3 VALUES IN (4) ENGINE = InnoDB,
 PARTITION part4 VALUES IN (5) ENGINE = InnoDB,
 PARTITION part5 VALUES IN (6) ENGINE = InnoDB,
 PARTITION part6 VALUES IN (7) ENGINE = InnoDB,
 PARTITION part7 VALUES IN (8) ENGINE = InnoDB,
 PARTITION part8 VALUES IN (9) ENGINE = InnoDB,
 PARTITION part9 VALUES IN (10) ENGINE = InnoDB,
 PARTITION part10 VALUES IN (11) ENGINE = InnoDB,
 PARTITION part11 VALUES IN (12) ENGINE = InnoDB,
 PARTITION part12 VALUES IN (0) ENGINE = InnoDB)  */;

`` ''

Нужно увидеть типы данных. Пожалуйста, предоставьте SHOW CREATE TABLE, включая указатели. Также нужно увидеть некоторые важные SELECTs; Часть проблемы состоит в том, чтобы выбрать лучшие индексы и выбросить остальные.

Rick James 28.08.2018 05:01

Я надеюсь, например, что "аэропорты" - это CHAR(3) CHARACTER SET ascii.

Rick James 28.08.2018 05:02

@RickJames. Это CHAR (3), но может не быть "ascii", будет ли это иметь большое значение?

Ben Osborne 28.08.2018 18:10

ascii - не большой diff. latin1 по существу эквивалентен ascii; utf8 / utf8mb4 будет излишним и может тратить впустую место. Но мне действительно нужен CREATE TABLE, чтобы помочь с вопросом производительности.

Rick James 28.08.2018 19:02

Привет, @RickJames, пожалуйста, посмотрите отредактированный вопрос.

Ben Osborne 30.08.2018 12:03
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
5
123
1

Ответы 1

Если есть 50M строк, но AUTO_INCREMENT=1258378560, позвольте указать на другую проблему, которая вырисовывается. (Это может быть связано с медленной загрузкой.)

`aid` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT

позволяет всего 4 миллиарда; у вас уже 1,2 миллиарда. Выполните небольшую математику, чтобы оценить, когда у вас закончатся идентификаторы. Решением перебора является переход на BIGINT, но давайте проанализируем Зачем, идентификаторы «сжигаются». Есть несколько способов, с помощью которых INSERT / REPLACE / etc могут выбросить идентификаторы. Опишите, пожалуйста, как работает импорт. REPLACE, пожалуй, худший - он сжигает идентификаторы и, фактически DELETE + INSERT. Другие методы быстрее.

(Сейчас я буду бродить по многим направлениям ...)

Разделение по месяцам (которое, как я полагаю, вы делаете с (startdatet), вероятно, не увеличивает производительности. Каков ваш опыт? (Обычно я выступаю против использования PARTITION, за исключением нескольких случаев использования, в которых есть преимущества. Я не вижу преимуществ в твоем случае.)

19 индексов означает 19 BT-деревьев, которые необходимо обновить. Перед завершением работы INSERT необходимо проверить 2 уникальных; остальные 17 могут быть отложены, но не навсегда. (Подробности обсуждаются в разделе «буфер изменений».)

Сколько оперативной памяти? Какая настройка у innodb_buffer_pool_size? Это должно быть около 70% ОЗУ. Буфер изменений является частью этого.

Я вижу как минимум 4 индекса, которые можно отбросить, поскольку другие индексы удовлетворяют их потребности. В общем, если у вас есть INDEX(a, b), вам также не нужен INDEX(a). (Сокращение с 19 индексов до 15 поможет некоторые.)

Флаги и другие вещи с низкой мощностью сами по себе практически бесполезны в качестве индексов. Оптимизатор решит, что сканировать таблицу дешевле, чем переключаться между BTree индекса и BTree данных. Я думаю о INDEX(rating).

Любой SELECT, который имеет нет, имеет startdatet в WHERE, скорее всего, будет помедленнее, чем без разделения. Это связано с тем, что запрос должен проверять все 13 разделов. Даже с AND startdatet = 4 производительность не будет лучше, чем если бы был индекс, включающий startdatet.

Позвольте мне обсудить любой индекс начало со столбцом (возможно, price, rating, startdate), который запрашивается как «диапазон» (например, WHERE price BETWEEN ...). Обработка не может использовать какие-либо столбцы после этого столбца. Я подозреваю, что ik_FILTER_ALL просканирует большой кусок индекса, поскольку он фильтруется только на price. Переставьте столбцы. Судя по названию, я предполагаю, что это «покрывающий» индекс. То есть общий запрос ссылается только на эти 6 столбцов? Примечание: SELECT * ... ссылается не только на эти 6, поэтому указатель не является «охватывающим». (Покажите нам вопрос; я могу обсудить его подробнее.)

Каждый из 5 индексов DirectFromPrice, вероятно, «идеален» для какого-либо запроса. Но они ужасно длинные (много столбцов). Я бы сказал предполагать, что 2 более коротких списка подошли бы близко к обработке 5 случаев "достаточно хорошо". (Помните, что уменьшение количества индексов поможет сократить время вставки.)

Какую версию MySQL / MariaDB вы используете?

Основная задача на этом этапе: показать нам импорт. (Я расскажу о сортировке ввода, увидев используемый метод.)

Спасибо за ответ. Что касается AUTO_INCREMENT=1258378560, это связано с тем, что мы используем такие операторы, как INSERT ON DUPLICATE KEY UPDATE, мы делаем это, потому что нам никогда не нужен день, когда этих данных нет, а также сделки строятся с течением времени, мы не получаем полных 50 миллионов за один день, а более 3/4 дней. Перегородки Это интересно, я могу оставить это, чтобы посмотреть, действительно ли он нам нужен. Я думаю, что это очень помогло с точки зрения производительности, но это было давно. 62 ГБ ОЗУ, совместимость с Aurora RDS MySQL, думаю, для innodb_buffer_pool_size установлено 52 ГБ.

Ben Osborne 31.08.2018 11:46

Другие вопросы по теме