MYSQL - Как исправить медленный запрос, который не использует индексы, как ускорить время ответа? - PullRequest
0 голосов
/ 16 января 2020

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

  1. Запрос в вопросе
    select f.*,ci.item_name 
    from forecastpro.current_item_forecast f 
        left join cat_items as ci on f.item_number=ci.item_number

Структуры таблиц

CREATE TABLE `current_item_forecast` (
   `Axe3` varchar(128) DEFAULT NULL,
   `Axe5` varchar(128) DEFAULT NULL,
   `Axe7` varchar(128) DEFAULT NULL,
   `Axe11` varchar(128) DEFAULT NULL,
   `Item_Number` varchar(40) NOT NULL,
   `Item_Name` varchar(128) DEFAULT NULL,
   `fc_year` int(4) NOT NULL,
   `fc_period` int(2) NOT NULL,
   `Qty_Forecast` double NOT NULL DEFAULT '0',
   `USD_Forecast` double NOT NULL DEFAULT '0',
   `Stock_Start` float NOT NULL DEFAULT '0',
   `Stock_Transit` float NOT NULL DEFAULT '0',
   PRIMARY KEY (`Item_Number`,`fc_year` DESC,`fc_period`),
   KEY `Item` (`Item_Number`),
   KEY `Axe3` (`Axe3`),
   KEY `Axe5` (`Axe5`),
   KEY `Axe7` (`Axe7`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

  CREATE TABLE `cat_items` (
   `Item_Number` char(32) NOT NULL,
   `Item_Name` char(128) DEFAULT NULL,
   `Axe3` char(10) DEFAULT NULL,
   `Item_Group` varchar(32) DEFAULT NULL,
   `Axe5` char(10) DEFAULT NULL,
   `Axe7` char(10) DEFAULT NULL,
   `Axe11` char(10) DEFAULT NULL,
   `Date_Created` datetime DEFAULT NULL,
   PRIMARY KEY (`Item_Number`),
   KEY `Item` (`Item_Number`)
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8

Объяснить

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  f       ALL                 121882  100.00  
1   SIMPLE  ci      ALL                 36838   100.00  Using where; Using join buffer (Block Nested Loop)

Другие попытки

**This two produce the same result:**

update forecastpro.current_item_forecast f
    left join cupfsa.cat_items ci on f.item_number=ci.item_number
set f.item_name=ci.item_name

update forecastpro.current_item_forecast f
    left join cupfsa.cat_items ci FORCE KEY FOR JOIN (PRIMARY) on f.item_number=ci.item_number
set f.item_name=ci.item_name

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   UPDATE  f       ALL                 76953   100.00  
1   SIMPLE  ci      ALL                 36838   100.00  Using where

Любая попытка запустить просто длится вечно.

Что бы вы порекомендовали?

Ответы [ 2 ]

2 голосов
/ 16 января 2020

Для вашего первого запроса на выборку вы можете попробовать добавить следующий индекс в таблицу cat_items:

CREATE INDEX idx ON cat_items (item_number, item_name);

В идеале это должно ускорить процесс левого соединения, поскольку каждая запись в current_item_forecast Таблица сопоставляется с таблицей cat_items, используя item_number в качестве поиска. Обратите внимание, что мы также включаем item_name в индекс, чтобы охватить предложение SELECT.

0 голосов
/ 17 января 2020

(Спасибо за предоставление CREATE TABLEs; причину root в вашей проблеме было бы очень трудно выяснить без них.)

Не смешивайте CHARACTER SETs, по крайней мере, когда JOINing от varchars. Это приводит к дорогостоящему сканированию таблицы.

current_item_forecast:
    `Item_Number` varchar(40) NOT NULL ... DEFAULT CHARSET=utf8mb4
cat_items:
   `Item_Number` char(32) ... DEFAULT CHARSET=utf8

Будьте последовательны по длине (40 против 32).

Поскольку PRIMARY KEY является уникальным ключом, не включайте избыточно KEY для того же столбца:

PRIMARY KEY (`Item_Number`),
KEY `Item` (`Item_Number`)

Используйте VARCHAR, если столбец действительно имеет фиксированную ширину.

...