SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 27.11.2007 15:14:59

Mikasto
Завсегдатай
Зарегистрирован: 25.09.2007
Сообщений: 35

Как задействовать индексы?

SELECT *
FROM
     `businesses` b
     LEFT JOIN `businesses` b2 ON b2.`id` = b.`id_parent`
     LEFT JOIN `businesses` b3 ON b3.`id` = b2.`id_parent`
     LEFT JOIN `businesses` b4 ON b4.`id` = b3.`id_parent`
     
WHERE 189 = b.id
      OR 189 = b.`id_parent`
      OR 189 = b2.`id_parent`
      OR 189 = b3.`id_parent`
      OR 189 = b4.`id_parent`   
LIMIT 2900, 10

EXPLAIN:
id    select_type    table    type    possible_keys    key    key_len    ref    rows    Extra
1    SIMPLE    b    ALL    PRIMARY,FK_businesses_parent,id_parent,id                2761   
1    SIMPLE    b2    eq_ref    PRIMARY,id    PRIMARY    4    billing.b.id_parent    1   
1    SIMPLE    b3    eq_ref    PRIMARY,id    PRIMARY    4    billing.b2.id_parent    1   
1    SIMPLE    b4    eq_ref    PRIMARY,id    PRIMARY    4    billing.b3.id_parent    1    Using where

Почему ALL ?

CREATE TABLE `businesses` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `id_parent` int(10) unsigned NOT NULL,
  `name` varchar(1600) NOT NULL,
  `path` tinytext,
  `document_type` tinyint(4) unsigned NOT NULL default '1',
  `document_sort` int(11) unsigned NOT NULL default '0',
  `document_gsort` varchar(255) character set utf8 collate utf8_bin NOT NULL,
  `document_level` int(11) unsigned NOT NULL default '0',
  `document_sub_folders` int(11) unsigned NOT NULL default '0',
  `document_sub_documents` int(11) unsigned NOT NULL default '0',
  `document_path` varchar(255) character set utf8 collate utf8_bin NOT NULL,
  `document_url` varchar(255) NOT NULL,
  `document_publish_time` int(10) unsigned NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `FK_businesses_parent` (`id_parent`),
  KEY `id_parent` (`id_parent`,`id`),
  KEY `id` (`id`,`id_parent`),
  CONSTRAINT `FK_businesses_parent` FOREIGN KEY (`id_parent`) REFERENCES `businesses` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Неактивен

 

#2 27.11.2007 15:45:27

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Как задействовать индексы?

А почему нет? Там же OR везде? Как бы Вы хотели "правильно" построить план?

Неактивен

 

#3 27.11.2007 16:05:34

Mikasto
Завсегдатай
Зарегистрирован: 25.09.2007
Сообщений: 35

Re: Как задействовать индексы?

paulus написал:

А почему нет? Там же OR везде? Как бы Вы хотели "правильно" построить план?

Я бы хотел во всех таблицах использовать индексы. Чтобы ни одна полностью не просматривалсь. С OR это исключено?

Неактивен

 

#4 27.11.2007 16:22:35

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Как задействовать индексы?

Ну, Вы подумайте, как написан Ваш запрос.

"Найди мне строчки, в которых или id 189, или у кого, возможно, есть родитель 189, или, возможно,
у родителя есть родитель 189, или, возможно, у родителя есть дедушка 189".

MySQL поступает правильно: он смотрит всех людей на наличие 189, а потом среди них смотрит
генеалогические связи. Вы бы искали по-другому?

Чтобы ускорить запрос, можете Выбрать не *, а id с правильным OR, а потом построить генеалогическое
дерево. Типа
SELECT id FROM businesses WHERE id=189 OR id_parent=189

Результат будет пробивать по индексу, он будет несколько избыточным, но с ним будет легко
делать LEFT JOIN.

Неактивен

 

#5 21.03.2008 11:31:40

Neval
Гуру
Откуда: Киев
Зарегистрирован: 11.03.2008
Сообщений: 449

Re: Как задействовать индексы?

Эммм... Поясните плз по использованию индексов.
Есть таблица, в ней есть составной индекс на 3 поля, ищем записи по этим трём полям (только по этим полям), порядок полей такой же, как указано в индексе, в итоге в эксплейне вижу "Using where".


Человек без чувства юмора - не серьёзный человек wink

Неактивен

 

#6 21.03.2008 12:11:48

Neval
Гуру
Откуда: Киев
Зарегистрирован: 11.03.2008
Сообщений: 449

Re: Как задействовать индексы?

Самое интересное - это поведение оптимизатора в данной ситуации.
В таблице есть два индекса:
key1 (1, 2, 3)
key2 (2, 1, 3)
Сделано это потому, что пока запросы не поправлены и они могут быть с поиском как по 1, 2, 3 полям, так и по 2, 1, 3.
У поля 2 CARDINALITY выше, по этому запрос с поиском по полям 1, 2, 3 использует всё же индекс key2, а не key1 smile
Т.е. получается, что порядок полей в данной ситуации не актуален :\


Человек без чувства юмора - не серьёзный человек wink

Неактивен

 

#7 21.03.2008 12:25:19

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: Как задействовать индексы?

Порядок полей в WHERE не важен, оптимизатор их упорядочит. Более того, не так уж важна cardinality отдельных частей составного индекса, см. http://sqlinfo.ru/forum/viewtopic.php?id=151#p1520

Важно какие условия накладываются. Если равенство или IN(), то будет использован весь составной индекс. Если есть неравенство, то оно завершает исползование индекса. Если есть неравенство по двум колонкам, то одна из них будет использована уже в WHERE. EXPLAIN показывает key_len - это длина использованной части индекса.

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson