MySQL не использует индекс в соединении таблиц - PullRequest
0 голосов
/ 29 апреля 2019

У меня есть 2 таблицы, product и product_pic с 100K строками.

У меня есть индекс porduct_id в таблице product_pic, но mysql не использует индекс при присоединении к ним!

CREATE TABLE `product` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(250) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `type` int(11) NOT NULL,
  `price` varchar(16) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `keyword` text CHARACTER SET utf8 NOT NULL,
  `summary` text COLLATE utf8_general_ci NOT NULL,
  `note` text CHARACTER SET utf8 NOT NULL,
  `catid` int(11) NOT NULL DEFAULT 0,
  `date` date NOT NULL DEFAULT '0000-00-00',
  `expdate` date NOT NULL DEFAULT '0000-00-00',
  `show` int(11) NOT NULL DEFAULT 0,
  `hit` int(11) NOT NULL,
  `userid` int(11) NOT NULL DEFAULT 0,
  `usertype` tinyint(4) NOT NULL DEFAULT 0,
  `rand` int(11) NOT NULL DEFAULT 0,
  `provinceid` tinyint(4) NOT NULL,
  `timestamp` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  `active` tinyint(4) NOT NULL,
  `expdate_email` tinyint(4) NOT NULL,
  `active_time` datetime NOT NULL,
  `update_time` datetime NOT NULL,
  `weight` float NOT NULL,
  `ucategory` int(11) NOT NULL DEFAULT -1,
  `searchstatus` tinyint(1) NOT NULL DEFAULT 0,
  `vitreen` tinyint(4) NOT NULL DEFAULT 1,
  `summery` varchar(256) COLLATE utf8_general_ci NOT NULL,
  `notification` varchar(255) COLLATE utf8_general_ci NOT NULL,
  `active_buy` tinyint(4) NOT NULL DEFAULT 1,
  `autotranslate` tinyint(1) NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`),
  KEY `usertype` (`usertype`),
  KEY `catid` (`catid`),
  KEY `active` (`active`),
  KEY `type` (`type`),
  KEY `userid` (`userid`),
  KEY `update_time` (`update_time`),
  FULLTEXT KEY `title` (`title`),
  FULLTEXT KEY `note` (`note`,`keyword`,`title`)
) ENGINE=InnoDB AUTO_INCREMENT=42987 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci ROW_FORMAT=DYNAMIC

рис продукта:

 CREATE TABLE `product_pic` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `userid` int(11) NOT NULL DEFAULT 0,
  `productid` int(11) NOT NULL DEFAULT 0,
  `pic` varchar(100) COLLATE utf8_general_ci NOT NULL DEFAULT '',
  `date` date NOT NULL DEFAULT '0000-00-00',
  `default_img` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `userid` (`userid`,`productid`),
  KEY `productid` (`productid`)
) ENGINE=InnoDB AUTO_INCREMENT=48020 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci 

Я пытаюсь использовать подсказку, но ничего не происходит!

наш запрос:

SELECT p.`id`, p.`title` name, product_pic.`pic` 
FROM `product` p
LEFT JOIN `product_pic` USE INDEX (productid)  ON p.`id`=product_pic.`productid`
where p.id in (SELECT * FROM `PID`) GROUP BY p.`id`;

Объяснить вывод:

+------+-------------+-------------+--------+---------------+---------+---------+------+------+-------------------------------------------------+
| id   | select_type | table       | type   | possible_keys | key     | key_len | ref  | rows | Extra                                           |
+------+-------------+-------------+--------+---------------+---------+---------+------+------+-------------------------------------------------+
|    1 | PRIMARY     | p           | ALL    | PRIMARY       | NULL    | NULL    | NULL |    1 | Using temporary; Using filesort                 |
|    1 | PRIMARY     | product_pic | ALL    | productid     | NULL    | NULL    | NULL |    1 | Using where; Using join buffer (flat, BNL join) |
|    1 | PRIMARY     | PID         | eq_ref | PRIMARY       | PRIMARY | 4       | p.id |    1 | Using index                                     |
+------+-------------+-------------+--------+---------------+---------+---------+------+------+-------------------------------------------------+

наш запрос занимает 3 минуты для 36 строк !!

36 rows in set (3 min 27.481 sec)

1 Ответ

1 голос
/ 02 мая 2019
  • Максимум 1 фото на каждый продукт?Если это так, вам не нужно GROUP BY.

  • . Если на один продукт есть несколько изображений, то GROUP BY используется неправильно - после GROUP BY, чтоproduct_pic. pic Вы хотите, чтобы это показывалось?

  • where p.id in (SELECT * FROM PID) -> JOIN PID USING(id)

  • Используется EXPLAINфиктивный - там написано ALL, но Rows=1, есть ли в каждой таблице только одна строка ??

  • Независимо от других изменений, измените KEY (productid) на KEY(productid, pic).

  • Избегайте указательных подсказок.

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