Почему Mysql использует индекс для одной таблицы, а не при объединении - PullRequest
0 голосов
/ 26 февраля 2020

Интересно, почему mysql использует индекс для запроса одной таблицы, а не для запроса на соединение, даже если я принудительно использую индекс.

Просто покажите таблицы и запросы:

show create table dc_assess_plan_batch;
CREATE TABLE `dc_assess_plan_batch` (
   `id` varchar(255) NOT NULL,
   `app_batch_id` varchar(255) NOT NULL COMMENT '数据来源的id ',
   `project_id` varchar(255) NOT NULL COMMENT '课程计划id',
   `name` varchar(32) DEFAULT NULL COMMENT '批次名',
   `time` datetime DEFAULT NULL COMMENT '批次的时间',
   `batch_id` varchar(255) DEFAULT NULL,
   `status` tinyint(4) DEFAULT NULL COMMENT '1.可用关系.0 不可用',
   `app_from` varchar(10) DEFAULT NULL COMMENT '数据来源',
   PRIMARY KEY (`id`),
   KEY `inx_project_id` (`project_id`) USING BTREE,
   KEY `app_batch_id` (`app_batch_id`) USING BTREE
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `dc_assess_task` (
   `id` varchar(255) NOT NULL,
   `name` varchar(255) DEFAULT NULL COMMENT '任务名称',
   `class_id` varchar(255) DEFAULT NULL COMMENT '班级id',
   `course_id` varchar(255) DEFAULT NULL COMMENT '课程id',
   `app_from` varchar(255) DEFAULT NULL COMMENT '成绩来源',
   `term_id` varchar(255) DEFAULT NULL COMMENT '学期id',
   `publish_time` datetime DEFAULT NULL COMMENT '任务发布时间',
   `completion_degree` double(10,3) DEFAULT NULL COMMENT '完成度',
   `course_name` varchar(255) DEFAULT NULL COMMENT '课程名称',
   `school_id` varchar(255) DEFAULT NULL,
   `app_batch_id` varchar(255) NOT NULL,
   `score_type` varchar(10) DEFAULT NULL COMMENT '''成绩计算规则 COUNT :按数量,  SCORE:按照分数, KCBCOUNT:按课程币数量'',',
   `xxpj_mode` enum('BY_GROUP','BY_PERSON') DEFAULT NULL COMMENT '线下评价评分模式',
   `upload_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '标志任务是否线下上传,1是,0否',
   PRIMARY KEY (`id`),
   KEY `FKrx8fxs12oe1mafttciiwir6cm` (`app_from`) USING BTREE,
   KEY `app_batch_id` (`app_batch_id`) USING BTREE
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Есть две таблицы, и обе имеют индекс в поле 'app_batch_id'

  • query1:
explain select * from dc_assess_plan_batch where app_batch_id = '2ebb4066038441229e937d2de4a9b5632018-12-07';

# id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
1   SIMPLE  dc_assess_plan_batch    ref app_batch_id    app_batch_id    767 const   1   Using index condition
  • query2
explain select * from dc_assess_plan_batch dapb join dc_assess_task dat on dapb.app_batch_id = dat.app_batch_id where dat.course_id = '562aecc2d1c64fabbff4a18496acc757';

# id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
1   SIMPLE  dapb    ALL app_batch_id                277947  
1   SIMPLE  dat ref app_batch_id    app_batch_id    767 ifass.dapb.app_batch_id 1   Using where

-query3

explain select * from dc_assess_plan_batch dapb force index (app_batch_id) join dc_assess_task dat on dapb.app_batch_id = dat.app_batch_id where dat.course_id = '562aecc2d1c64fabbff4a18496acc757';

# id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
1   SIMPLE  dapb    ALL app_batch_id                277947  
1   SIMPLE  dat ref app_batch_id    app_batch_id    767 ifass.dapb.app_batch_id 1   Using where

Почему индекс на app_batch_id не работает при объединении, даже форсировать с использованием индекса

1 Ответ

0 голосов
/ 27 февраля 2020

Что работает быстрее? Иногда «Оптимизатор знает лучше». Тем не менее, EXPLAINs выглядит одинаково?

Я ожидаю, что они значительно помогут с производительностью:

dat:  (course_id, app_batch_id)  -- the table has nothing like this
dapb:  (app_batch_id)

При просмотре JOIN оптимизатор обычно смотрит на WHERE предложение, чтобы решить, с какой таблицы начать. Но, увы, индекса для dat.course_id нет. ТАК КАК ему нужно выполнить запрос "грубой силой" - просканируйте все из одной таблицы, затем перейдите в другую. Сильный ключ к этому - ALL .. 277947 в EXPLAIN. Это говорит о том, что он не может извлечь выгоду из любого доступного индекса на dat.

Если бы у него был такой индекс, Оптимизатор начинал бы с dat, достигал, возможно, 1 строки, а не 277947, затем достигал в другую таблицу, используя уже имеющийся индекс, даже без использования FORCE INDEX.

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