Есть ли способ оптимизировать этот запрос? ОБЪЕДИНИТЬ несколькими строками в MySQL

#mysql

#mysql

Вопрос:

Мне нужно выполнить этот запрос:

 SELECT min(d.id) id, p.SERIAL serial, p.pos_id pos_id, MIN(fecha) fecha
FROM pvs p
JOIN devices d
ON d.SERIAL=p.SERIAL
GROUP BY p.SERIAL, p.pos_id
ORDER BY p.pos_id ASC;
  

Проблема в том, что «pvs» — это очень длинная таблица с более чем 3 миллионами строк. Это таблица, в которую я загружаю необработанные данные, но затем я пытаюсь получить идентификатор этих элементов в рабочей базе данных (отсюда минимальное (d.id ) часть). это также причина, по которой я не добавил внешний ключ как таковой в pos_id в pvs.

Структура следующая:

 CREATE TABLE pvs (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `pos_id` INT(11) NOT NULL,
    `estado` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci',
    `fecha` DATETIME NOT NULL,
    `serial` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci',
    `created_at` TIMESTAMP NULL DEFAULT NULL,
    `updated_at` TIMESTAMP NULL DEFAULT NULL
)

CREATE TABLE devices (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `serial` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
    `rotulo` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
    `code` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
    `cost_center` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
    `guia_recepcion` INT(11) NULL DEFAULT NULL,
    `guia_reversa` INT(11) NULL DEFAULT NULL,
    `pep` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
    `modified_by` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
    `modified_on` DATETIME NULL DEFAULT NULL,
    `fecha_recepcion` DATETIME NULL DEFAULT NULL,
    `fecha_instalacion` DATETIME NULL DEFAULT NULL,
    `fecha_reversa` DATETIME NULL DEFAULT NULL,
    `status_id` INT(10) UNSIGNED NOT NULL,
    `location_id` VARCHAR(255) NOT NULL COLLATE 'utf8mb4_unicode_ci',
    `customer_id` INT(10) UNSIGNED NOT NULL,
    `str_id` INT(10) UNSIGNED NOT NULL,
    `model_id` INT(10) UNSIGNED NOT NULL,
    `pos_id` INT(11) NOT NULL,
    `user_id` INT(10) UNSIGNED NOT NULL,
    `technician_id` INT(10) UNSIGNED NOT NULL,
    `created_at` TIMESTAMP NULL DEFAULT NULL,
    `updated_at` TIMESTAMP NULL DEFAULT NULL,
    `serial_prev` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
    `reversa_prev` DATETIME NULL DEFAULT NULL
)
  

Должен ли я сделать p.serial внешним ключом, даже если это varchar? Если я просто использую p.pos_id в качестве предложения join, «идентификаторы» совпадают. Я сгруппировал его с помощью min (), потому что мне нужно было добавить его в select, не добавляя его в «group by». Мне нужны те же столбцы для запроса.

Редактировать:

Объяснение выбора

Комментарии:

1. является d.serial уникальным?

2. Нет, это не так. Он может отображаться в нескольких идентификаторах.

3. Как насчет p.serial ? это уникально?

4. Нет, это не так. Эта таблица отслеживает состояние устройства в местоположении, и на самом деле они часто повторяются.

Ответ №1:

убедитесь, что у вас правильный индекс

     create index  idx1 on pvs( SERIAL); 
  

и

     create index  idx2 on devices ( SERIAL); 
  

Комментарии:

1. Тогда это не ответ.

2. почему не может быть проиндексирован???? индексы могут быть уникальными или не уникальными, и в этом случае два не уникальных индекса могут решить проблему производительности..

3. Индекс может быть либо уникальным , либо не уникальным … unioque — это просто ограничение для индекса .. как вы можете видеть в документе mysql dev.mysql.com/doc/refman/8.0/en/create-index.html уникальный — это вариант ..

4. @scaisEdge виноват, я думал, что индексы должны быть уникальными, спасибо

5. Я все еще создаю индекс. Это занимает много времени.