объединение в индексированных полях не использует индексы - PullRequest
0 голосов
/ 22 февраля 2019

У меня есть два стола.Я написал запрос, чтобы присоединиться к ним на один столбец.Этот столбец индексируется в обеих таблицах, но MySQL не использует индексы.Может ли кто-то а) сказать мне, почему и б) рассказать, как я могу заставить MySQL использовать индекс для быстрого объединения этих таблиц.

Первая таблица:

CREATE TABLE `dol_msa_zip_assoc` (
  `pkey` int(5) unsigned NOT NULL AUTO_INCREMENT,
  `zip` varchar(5) NOT NULL DEFAULT '',
  `pmsa_msa` varchar(5) NOT NULL DEFAULT '',
  PRIMARY KEY (`pkey`),
  KEY `zip` (`zip`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

Содержит 42690 записей.

Другая таблица:

CREATE TABLE `v3_msa_zip_assoc` (
  `pkey` int(5) unsigned NOT NULL AUTO_INCREMENT,
  `zip` varchar(9) NOT NULL DEFAULT '',
  `pmsa_msa` varchar(6) NOT NULL DEFAULT '',
  PRIMARY KEY (`pkey`),
  KEY `zip` (`zip`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1;

содержит 42486 записей.

Мой запрос, предназначенный для поиска записей в первой таблице, а не во второй:

SELECT d.*, o.* FROM `dol_msa_zip_assoc` d
LEFT JOIN `v3_msa_zip_assoc` o
ON o.zip = d.zip
WHERE o.zip IS NULL

Когда я ОБЪЯСНЯЮ этот запрос, я вижу, что индексы в столбце zip не используются:

+----+-------------+-------+------+---------------+------+---------+------+-------+----------------------------------------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra                                                          |
+----+-------------+-------+------+---------------+------+---------+------+-------+----------------------------------------------------------------+
|  1 | SIMPLE      | d     | ALL  | NULL          | NULL | NULL    | NULL | 42915 | NULL                                                           |
|  1 | SIMPLE      | o     | ALL  | NULL          | NULL | NULL    | NULL | 42486 | Using where; Not exists; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------+---------------+------+---------+------+-------+----------------------------------------------------------------+

Что может быть причиной этой ошибки при использовании индексов?Это потому, что один столбец zip является latin1, а другой utf8?Как я могу получить этот запрос для использования индексов, чтобы не требовалось времени для запуска?

РЕДАКТИРОВАТЬ: изменение порядка JOIN, очевидно, использует индекс:

SELECT d . * , o . *
FROM `v3_msa_zip_assoc` o
LEFT JOIN `dol_msa_zip_assoc` d ON d.zip = o.zip
WHERE d.zip IS NULL

Вот объяснение:

+----+-------------+-------+------+---------------+------+---------+------+-------+-------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | Extra                   |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------------------+
|  1 | SIMPLE      | o     | ALL  | NULL          | NULL | NULL    | NULL | 42486 | NULL                    |
|  1 | SIMPLE      | d     | ref  | zip           | zip  | 17      | func |     1 | Using where; Not exists |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------------------+

РЕДАКТИРОВАТЬ 2: Я изменил структуру старой таблицы, чтобы использовать сопоставления utf8.Теперь оно определено так:

CREATE TABLE `v3_msa_zip_assoc` (
  `pkey` int(5) unsigned NOT NULL AUTO_INCREMENT,
  `zip` varchar(9) NOT NULL DEFAULT '',
  `pmsa_msa` varchar(6) NOT NULL DEFAULT '',
  PRIMARY KEY (`pkey`),
  KEY `zip` (`zip`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

Это, похоже, исправило проблему:

mysql> EXPLAIN SELECT d . * , o . *
    -> FROM `dol_msa_zip_assoc` d
    -> LEFT JOIN `v3_msa_zip_assoc` o ON o.zip = d.zip
    -> WHERE o.zip IS NULL;
+----+-------------+-------+------+---------------+------+---------+---------------------+-------+-------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref                 | rows  | Extra                   |
+----+-------------+-------+------+---------------+------+---------+---------------------+-------+-------------------------+
|  1 | SIMPLE      | d     | ALL  | NULL          | NULL | NULL    | NULL                | 42915 | NULL                    |
|  1 | SIMPLE      | o     | ref  | zip           | zip  | 29      | myplan_v4_dev.d.zip |     1 | Using where; Not exists |
+----+-------------+-------+------+---------------+------+---------+---------------------+-------+-------------------------+

1 Ответ

0 голосов
/ 22 февраля 2019

Это набор символов, который запрещает использование индекса.

Один из столбцов zip - latin1, другой - utf8.

Существует неявное преобразование, эквивалентное CONVERT(zip USING charset) наодна сторона,

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