Индекс Mysql не берется, а поле упоминается в предложении join on - PullRequest
0 голосов
/ 27 августа 2018
explain select * from users u join wallet w on w.userId=u.uuid where w.userId='8319611142598331610'; //Index is taken

enter image description here

explain select * from users u join wallet w on w.userId=u.uuid where w.currencyId=8; //index is not taken

enter image description here

Как видно выше, индекс userIdIdx используется в последнем случае, но не в первом.

Ниже приведена схема двух таблиц -

CREATE TABLE `users` (
  `uuid` varchar(600) DEFAULT NULL,
  KEY `uuidIdx` (`uuid`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `wallet` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `userId` varchar(200) NOT NULL DEFAULT '',
  `currencyId` int(11) NOT NULL,
  PRIMARY KEY (`Id`),
  KEY `userIdIdx` (`userId`),
  KEY `currencyIdIdx` (`currencyId`)
) ENGINE=InnoDB AUTO_INCREMENT=279668 DEFAULT CHARSET=latin1;

Как заставить MySql учитывать индекс userIdIdx или uuidIdx?

Ответы [ 2 ]

0 голосов
/ 28 августа 2018

Оба запроса делают все возможное с тем, что вы им дали.

select  *
    from  users u
    join  wallet w  ON w.userId=u.uuid
    where  w.userId='8319611142598331610';

select  *
    from  users u
    join  wallet w  ON w.userId=u.uuid
    where  w.currencyId=8;

Если в таблице только одна строка (например, users), оптимизатор выбирает другой путь. Похоже, именно это и произошло с первым запросом.

В противном случае оба запроса начнутся с wallet, поскольку происходит фильтрация. Каждый из вторичных ключей в wallet удобен для одного из запросов. Еще лучше было бы

INDEX(userId, currencyId, id)  -- for first query
INDEX(currencyId, userId, id)  -- for second query

Первый столбец используется в WHERE; два других столбца делают индекс «покрывающим», так что ему не нужно прыгать между индексом и данными.

(Боже, у этих таблиц ужасно мало столбцов.)

После фильтрации в w он переходит к u и использует INDEX(uuid). Поскольку это единственный столбец в таблице (без имени ??), это может быть «Использование индекса», то есть «покрытие».

И единственная причина для достижения u состоит в том, чтобы убедиться, что существует пользователь со значением, совпадающим с w.userId. Поскольку у вас это, вероятно, всегда есть, почему в запросе от JOIN до users

0 голосов
/ 27 августа 2018

Есть два метода, улучшающие это.

Метод 1:

Добавление индекса из нескольких столбцов wallet(userId, currencyId) выглядит лучше для обоих запросов.

см. Демонстрацию https://www.db -fiddle.com / f / aesNYevEzwopmXrnQJRPoS / 0

Метод 2

Перепишите запрос.
Это работает с текущей структурой таблицы.

Запрос

SELECT 
 *
FROM (
  SELECT 
   wallet.userId
  FROM 
   wallet 
  WHERE
   wallet.currencyId = 8
) AS wallet
INNER JOIN 
 users
ON
 wallet.userId = users.uuid

см. Демонстрацию https://www.db -fiddle.com / f / aesNYevEzwopmXrnQJRPoS / 3

p.s Я также советую вам также добавить Id int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY в таблицу пользователей, когда вы используете InnoDB в качестве механизма таблиц. Этот пост от моего объясняет, почему https://dba.stackexchange.com/a/48184/27070

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