Задавайте вопросы, мы ответим
Вы не зашли.
Здравствуйте!
MySQL 5.5.19.Помогите разобраться с индексами.
Есть две маленькие таблицы-"справочники". примерно по 50 записей в каждой.
CREATE TABLE `a` (
`ida` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(45) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`ida`)
) ENGINE=InnoDB
CREATE TABLE `b` (
`idb` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(45) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`idb`)
) ENGINE=InnoDB
И одна большая, которая их использует.Примерно 7 000 000 записей.
CREATE TABLE `state` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`ida` int(10) unsigned NOT NULL,
`idb` int(10) unsigned NOT NULL,
`dt` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_a_ida` (`ida`),
KEY `fk_b_idb` (`idb`),
KEY `index_1` (`ida`,`idb`,`dt`),
CONSTRAINT `fk_a_ida` FOREIGN KEY (`ida`) REFERENCES `a` (`ida`) ,
CONSTRAINT `fk_b_idb` FOREIGN KEY (`idb`) REFERENCES `b` (`idb`) ,
) ENGINE=InnoDB
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type
state 0 PRIMARY 1 id A 7238053 NULL NULL BTREE
state 1 fk_a_ida 1 ida A 18 NULL NULL BTREE
state 1 fk_b_idb 1 idb A 18 NULL NULL BTREE
state 1 index_1 1 ida A 18 NULL NULL BTREE
state 1 index_1 2 idb A 6598 NULL NULL BTREE
state 1 index_1 3 dt A 6598 NULL NULL BTREE
-----------------------------------------------------------
Делаем выборку(STRAIGHT_JOIN стоит намеренно ради эксперимента):
explain select STRAIGHT_JOIN state.id,a.name,b.name,state.dt
from ((a join b) join state)
where state.ida = a.ida and state.idb = b.idb
and state.dt BETWEEN '2011-06-22 23:00:00' AND '2011-06-23 00:00:00' ;
Получаем:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE a ALL PRIMARY NULL NULL NULL 31
1 SIMPLE b ALL PRIMARY NULL NULL NULL 57 "Using join buffer"
1 SIMPLE state ref fk_a_ida,fk_b_idb,index_1 index_1 8 a.ida,b.idb 1097 "Using where; Using index"
ПОЧЕМУ mySQL не использовал третью колонку `dt` индекса для выборки диапазона?
Неактивен
Подозреваю, что это просто такое отображение. Учитывая, что там Using index,
он третью часть индекса таки использует.
Чтобы убедиться — уберите условие с датой и посмотрите на оценку количества
строк.
Неактивен
paulus написал:
Подозреваю, что это просто такое отображение. Учитывая, что там Using index,
он третью часть индекса таки использует.
Чтобы убедиться — уберите условие с датой и посмотрите на оценку количества
строк.
select STRAIGHT_JOIN state.id,a.name,b.name,state.dt
from ((a join b) join state)
where state.ida = a.ida and state.idb = b.idb
;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE a ALL PRIMARY NULL NULL NULL 31
1 SIMPLE b ALL PRIMARY NULL NULL NULL 57 "Using join buffer"
1 SIMPLE state ref fk_a_ida,fk_b_idb,index_1 index_1 8 a.ida,.b.idb 1824 "Using index"
-----------------------------------------------------------------
Я привел не совсем показательный select.Все выдаваемые поля присутствуют в индексе и похоже не сканируется сама таблица.
Добавим колонку в таблицу state и попробуем сделать select с этим полем:
ALTER TABLE `gorsvet`.`state` ADD COLUMN `test` VARCHAR(45) NULL ;
explain select STRAIGHT_JOIN state.id,a.name,b.name,state.dt,state.test
from ((a join b) join state)
where state.ida = a.ida and state.idb = b.idb
and state.dt BETWEEN '2011-06-22 23:00:00' AND '2011-06-23 00:00:00'
;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE a ALL PRIMARY NULL NULL NULL 31
1 SIMPLE b ALL PRIMARY NULL NULL NULL 57 "Using join buffer"
1 SIMPLE state ref fk_a_ida,fk_b_idb,index_1 index_1 8 a.ida,b.idb 1824 "Using where"
Вот тут то уж точно третья колонка 'dt' индекса не используется. type=ref, key_len=8(ida+idb).
Да и время выполнения запроса - 12288 rows in set (8 min 51.85 sec).
Неактивен
Угу, в данном случае не понятно. Ну то есть логика рассуждений такая — Вы выбираете
почти все данные без условия, поэтому полный скан должен работать быстрее выборки
по индексу. Проблема в том, что seekи всё равно уже будут, и в этом месте, кажется,
таки бага.
Неактивен