Что я могу сделать, чтобы сделать этот MySQL запрос быстрее (ответ <1с) - PullRequest
0 голосов
/ 11 апреля 2020

Чтобы объяснить контекст. На работе мы запускаем приложение java, которое использует MySQL в качестве кэша данных. Мы выполняем некоторые медленные процессы Монте-Карло, чтобы получить некоторые результаты. Затем мы вставляем их в базу данных для последующего использования, поэтому нам не нужно снова делать дорогостоящий Монте-Карло для той же конфигурации.

Вот код создания таблицы:

CREATE TABLE `cache_lte_perfbe_saved` (
`CNUMZONE` DECIMAL(10,5) NOT NULL,
`IDDATASET` INT(11) NOT NULL,
`CRB` INT(11) NOT NULL,
`CENVIRONMENT` VARCHAR(45) NOT NULL,
`CPROPAGATION` VARCHAR(45) NOT NULL,
`CSECTORCONF` VARCHAR(60) NOT NULL,
`CFREQUENCY` INT(11) NOT NULL,
`CINTERCELLLOAD` INT(11) NOT NULL,
`CNBST` INT(11) NOT NULL,
`CNBBE` INT(11) NOT NULL,
`IDLTECONF` INT(11) NOT NULL,
`CTHROUGHPUT` VARCHAR(50) NOT NULL,
`CTHROUGHPUT_ARITHMETIC` DECIMAL(9,2) NOT NULL,
`CDISTRIB` DECIMAL(12,10) NOT NULL,
`VOLTETRAFFICGB` VARCHAR(50) NOT NULL,
`PID` VARCHAR(45) NOT NULL DEFAULT '0',
`SERVICENAME` VARCHAR(50) NOT NULL,
`VOLTETRAFFICERL` VARCHAR(50) NOT NULL,
PRIMARY KEY (`IDDATASET`, `CRB`, `CNBST`, `CNBBE`, `IDLTECONF`, `CNUMZONE`, `CENVIRONMENT`, `CPROPAGATION`, `CFREQUENCY`, `CINTERCELLLOAD`, `SERVICENAME`, `PID`, `VOLTETRAFFICGB`, `VOLTETRAFFICERL`, `CSECTORCONF`) USING HASH,
INDEX `PK_noVoltenoSectorConf` (`IDDATASET`, `CRB`, `CENVIRONMENT`, `CPROPAGATION`, `CFREQUENCY`, `CINTERCELLLOAD`, `CNBST`, `CNBBE`, `IDLTECONF`, `PID`) USING HASH,
INDEX `PK_noVoLTE` (`IDDATASET`, `CRB`, `CENVIRONMENT`, `CPROPAGATION`, `CSECTORCONF`, `CFREQUENCY`, `CINTERCELLLOAD`, `CNBST`, `CNBBE`, `IDLTECONF`, `PID`) USING HASH,
INDEX `PK_noVoLTEnoFrequency` (`IDDATASET`, `CRB`, `CENVIRONMENT`, `CPROPAGATION`, `CSECTORCONF`, `CNBST`, `CNBBE`, `PID`, `IDLTECONF`) USING HASH)COLLATE='utf8_general_ci' ENGINE=InnoDB ;

Вот один запрос, который занимает около 3 секунд:

SELECT  *
    FROM  cache_lte_perfbe_saved
    WHERE  IDDATASET = 6
      AND  CRB = 100
      AND  CENVIRONMENT = 'high'
      AND  CPROPAGATION = 'IndDay'
      AND  CFREQUENCY = 1800
      AND  CINTERCELLLOAD = 82.0
      AND  CNBST >= 0
      AND  CNBST <= 0
      AND  CNBBE <= 30
      AND  PID = 1586536071412
      AND  IDLTECONF IN ( 2, 17, 18 )
      AND  VOLTETRAFFICERL = 40.0
    UNION 
 SELECT  *
    FROM  cache_lte_perfbe
    WHERE  IDDATASET = 6
      AND  CRB = 100
      AND  CENVIRONMENT = 'high'
      AND  CPROPAGATION = 'IndDay'
      AND  CFREQUENCY = 2600
      AND  CINTERCELLLOAD = 88.0
      AND  CNBST >= 0
      AND  CNBST <= 0
      AND  CNBBE <= 30
      AND  PID = 1586536071412
      AND  IDLTECONF IN ( 2, 17, 18 )
      AND  VOLTETRAFFICERL = 40.0
    UNION 
 SELECT  *
    FROM  cache_lte_perfbe
    WHERE  IDDATASET = 6
      AND  CRB = 50
      AND  CENVIRONMENT = 'high'
      AND  CPROPAGATION = 'IndDay'
      AND  CFREQUENCY = 800
      AND  CINTERCELLLOAD = 84.0
      AND  CNBST >= 0
      AND  CNBST <= 0
      AND  CNBBE <= 30
      AND  PID = 1586536071412
      AND  IDLTECONF IN ( 2, 17, 18 )
      AND  VOLTETRAFFICERL = 40.0 

[/ code]

Вот результат объяснения этого запроса: click

Запрос возвращает 3000 строк.

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

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

Дайте мне знать, что вы думаете. Ура!

1 Ответ

0 голосов
/ 12 апреля 2020
  • Переставьте PRIMARY KEY так, чтобы эти столбцы были первыми: IDDATASET, CRB, CENVIRONMENT, CPROPAGATION, CFREQUENCY, CINTERCELLLOAD, PID, VOLTETRAFFICERL. Неважно, в каком порядке они находятся. (Подробнее ниже)
  • Бросьте любые второстепенные индексы, которые доставляют больше хлопот, чем стоят. Вероятно, вы можете избавиться от всех трех из них. (Это не будет напрямую ускорять SELECT, но заставит INSERTs работать быстрее, следовательно, останется в стороне.)
  • Если вам нужны эти индексы , при аренде переставьте столбцы, чтобы сначала проверить все столбцы с = constant. После этого редко можно использовать более одного столбца 'range'.
  • Даже если вам все еще нужны все 3 индекса, может быть лучше иметь только начальный список общих столбцов. (Покажите различные SELECTs/UPDATEs/DELETEs для дальнейшего объяснения.)
  • Обратите внимание, что "HA SH" молча заменяется на "Btree".
  • Используйте UNION ALL вместо UNION DISTINCT ( DISTINCT по умолчанию, но медленнее). (Если вы ожидаете сбой, но не хотите их, игнорируйте это предложение.)
  • 5.7.3 (10.1) имеет оптимизацию для UNION ALL; при необходимости обновите.
  • Если таблица настолько велика, что она связана с вводом / выводом, уменьшите INTs (по 4 байта каждая) на меньшие типы данных. И рассмотрите возможность использования 1-байта ENUM для CENVIRONMENT, et c.
  • Внимание! При сравнении значения VARCHAR с числовым значением c индекс не может быть эффективно использован. Я особенно думаю о VOLTETRAFFICERL, но проверьте остальные!

Проблема с порядком в ПК ...

Обратите внимание на "key_len = 12" в EXPLAIN. 12 = 3 * 4. То есть использовались первые 3 столбца, без учета остальных,

 PRIMARY KEY (`IDDATASET`, `CRB`, `CNBST`, ...
               ---------    ---    -----

INT - 4 байта. WHERE имеет

    WHERE      IDDATASET = 6
      AND                   CRB = 100
      AND                          CNBST >= 0
               ---------    ---    -----

Остальные столбцы не используются. Почему? Во многих ситуациях будут использоваться только первые несколько столбцов индекса:

  • Сначала любые столбцы, которые проверяются с =
  • Затем, one столбец диапазона.
  • После этого все остальные тесты выполняются методом грубой силы.

Отсюда мое предложение переставить PK.

Предупреждение: переставить ПК займет много времени; ALTER будет полностью перестроить таблицу (и использовать кучу дискового пространства).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...