Модераторы: skyboy

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> MySQL - индексы - ORDER BY, И снова он, ман не помогает 
:(
    Опции темы
-=Ustas=-
Дата 19.9.2006, 22:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ustix IT Group
****


Профиль
Группа: Участник Клуба
Сообщений: 2222
Регистрация: 21.1.2005
Где: Краснодар

Репутация: 4
Всего: 69



Мое почтение!
Уже бесить начинает, либо просто отдохнуть надо! Дело вот в чем: В книге написано что инедксы ставятся на те поля, которые учавсвуют в WHERE условии или в ORDER BY выражении. Есть такая таблица (обрисую образно, на самом деле там таблица гораздо больше и не одна, в запросе учавствует, но этот пример за образец прокатит):
Код

DROP TABLE IF EXISTS `category`;
CREATE TABLE `category` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `name` varchar(50) collate cp1251_bin NOT NULL default '',
  `title` varchar(255) collate cp1251_bin NOT NULL default '',
  `created` int(10) NOT NULL default '0',
  `modified` int(10) NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `name` (`name`),
  KEY `created` (`created`),
  KEY `modified` (`modified`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251 COLLATE=cp1251_bin;

В ней более 50 000 записей. Цифра не значительная, т.к. в постгрисе пашет на ура. Далее... делабюю запрос:
Код

SELECT * FROM `category` ORDER BY `created`

Ноль реакции, EXPLAIN пишет что кеи не юзаются и using filesort, т.е. понятно что перебирает всю таблицу. 
Делаю такой запрос:
Код

SELECT * FROM `category` WHERE `created` > 0 ORDER BY `created` 

`created` - это int - unix_timestamp, ясно что он никогда 0 равняться не будет. Кей начинает быть заюзаным, EXPLAIN в extra показывает using where, т.е. применение индексу пошло. И выполняется моментально (ну как и должно в принципе быть).
Так вот я что-то вообще не пойму эту систему, что надо делать чтоб желаемые индекированые поля были использованы в запросе? Это же не выход, добавлять голимые условия в WHERE !!!
Плз, обяъсните, или ткните носом. 

P.S. В мане читал, и читал из этой темы http://forum.vingrad.ru/index.php?showtopi...st&p=828643 но так нифига и не понял  smile  Блин....


--------------------
В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм.
-----
PM WWW ICQ Skype   Вверх
muzer
Дата 20.9.2006, 01:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 387
Регистрация: 31.8.2006

Репутация: 30
Всего: 31



Вы упоминули, что в запросе участвует не одна таблица, это важно. Покажите запрос целиком.
Дело в том, что при джойне нескольких таблиц использовать индекс для сортировки уже сложнее, и он его начинает использовать только(?), если уже использует его же для WHERE (типа а почему бы не применить заодно для ORDER BY) и то не всегда (думаю, зависит от порядка джойна таблиц).

А описанный пример вообще должен в обоих случаях использовать индекс. Если не хочет - можно ему сказать после имени таблицы: FORCE INDEX (имя_индекса). 

Это сообщение отредактировал(а) muzer - 20.9.2006, 01:35
PM WWW   Вверх
-=Ustas=-
Дата 20.9.2006, 08:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ustix IT Group
****


Профиль
Группа: Участник Клуба
Сообщений: 2222
Регистрация: 21.1.2005
Где: Краснодар

Репутация: 4
Всего: 69



Цитата(muzer @  20.9.2006,  01:34 Найти цитируемый пост)
А описанный пример вообще должен в обоих случаях использовать индекс.

Я тоже так думал...но...

Цитата(muzer @  20.9.2006,  01:34 Найти цитируемый пост)
Вы упоминули, что в запросе участвует не одна таблица, это важно. Покажите запрос целиком.

Вот табличка:
Код

CREATE TABLE `shop_product` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `pid` int(10) unsigned NOT NULL default '0',
  `tid` mediumint(6) unsigned NOT NULL default '0',
  `name` varchar(50) collate cp1251_bin NOT NULL default '',
  `title` varchar(255) collate cp1251_bin NOT NULL default '',
  `description` text collate cp1251_bin NOT NULL,
  `pages` int(10) unsigned NOT NULL default '0',
  `picture` varchar(60) collate cp1251_bin default NULL,
  `count` int(10) unsigned NOT NULL default '0',
  `rating` int(10) unsigned NOT NULL default '0',
  `fname` varchar(255) collate cp1251_bin NOT NULL default '',
  `fhash` varchar(255) collate cp1251_bin NOT NULL default '',
  `fid` mediumint(6) NOT NULL default '0',
  `year` int(10) unsigned default NULL,
  `price` float default '0',
  `sort` int(10) NOT NULL default '0',
  `letter` char(1) collate cp1251_bin NOT NULL default '',
  `active` enum('Y','N') collate cp1251_bin NOT NULL default 'N',
  `created` int(10) NOT NULL default '0',
  `modified` int(10) NOT NULL default '0',
  `comments` text collate cp1251_bin NOT NULL,
  `content` text collate cp1251_bin NOT NULL,
  `about` text collate cp1251_bin NOT NULL,
  `cuser` int(10) NOT NULL default '1',
  `muser` int(10) NOT NULL default '1',
  `last` int(10) NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `pid` (`pid`),
  KEY `tid` (`tid`),
  KEY `count` (`count`),
  KEY `rating` (`rating`),
  KEY `fid` (`fid`),
  KEY `sort` (`sort`),
  KEY `letter` (`letter`),
  KEY `last` (`last`),
  KEY `created` (`created`),
  FULLTEXT KEY `title` (`title`),
  FULLTEXT KEY `description` (`description`),
  FULLTEXT KEY `comments` (`comments`),
  FULLTEXT KEY `content` (`content`),
  FULLTEXT KEY `about` (`about`),
  FULLTEXT KEY `all` (`title`,`description`,`content`,`about`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251 COLLATE=cp1251_bin;

Вот собсна сам запрос:
Код

SELECT 
    p.`id`, 
    p.`title`, 
    p.`active`, 
    p.`created`, 
    c.`id` AS `catID`, 
    c.`title` AS `catTitle` 
FROM 
    shop_product AS `p` 
INNER JOIN 
    shop_category AS `c` 
ON 
    p.`pid` = c.`id` 
WHERE 
    p.`active` = 'Y' 
ORDER BY 
    p.`created` 
DESC 
LIMIT 7

Выполняется где-то секунд 30. Вот результаты EXPLAIN:
Код

id  select_type  table  type  possible_keys  key  key_len   ref             rows   Extra  
1   SIMPLE          c   ALL     PRIMARY     NULL    NULL    NULL            225    Using temporary; Using filesort 
1   SIMPLE          p   ref     pid         pid     4       naukashop.c.id  145    Using where 



--------------------
В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм.
-----
PM WWW ICQ Skype   Вверх
Bikutoru
Дата 20.9.2006, 11:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Увлекающийся
**


Профиль
Группа: Участник
Сообщений: 522
Регистрация: 24.5.2005
Где: Москва

Репутация: 1
Всего: 22



Немного не в тему, но все же:
unix_timestamp - это же неотрицательное число. Может тогда следует объявить и само поле не
Код

 `created` int(10) NOT NULL default '0',

а как 
Код

 `created` int(10) UNSIGNED NOT NULL default '0',


И такой вопрос: а чем именно обусловлен выбор int + unix_timestamp. Как я понял (из таблиц) у нас есть категории и продукты с датами создания и модификации. Мне кажется, что здесь гораздо лучше использовать тип TIMESTAMP, который обладает возможностью автоматического обновления своего значения.
http://dev.mysql.com/doc/refman/5.0/en/timestamp-4-1.html

Добавлено @ 11:21 
Пока искал информацию о timestamp'е нашел такую вещь
http://dev.mysql.com/doc/refman/5.0/en/datetime.html
(см. сообщение в комментариях)


--------------------
Человек, словно в зеркале мир — многолик, 
Он ничтожен — и он же безмерно велик!
Омар Хайям
PM   Вверх
muzer
Дата 20.9.2006, 11:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 387
Регистрация: 31.8.2006

Репутация: 30
Всего: 31



Цитата(-=Ustas=- @  20.9.2006,  09:12 Найти цитируемый пост)
Я тоже так думал...но...

Что "но"? Не вижу ни одного опровержения, посмотрите explain'ы к тем запросам, которые у вас в первом примере, увидите сами.

-=Ustas=-, а какой индекс он должен по-вашему использовать? smile 
Логично ведь, что сначала он выбирает категории, потом все товары из выбранных категорий, затем отбирает только активные, затем сортирует. Можно попробовать его заставить сначала товары отбирать, т.е. STRAIGHT_JOIN после SELECT написать и оставить порядок таблиц такой же. Но я всё равно не уверен, что он начнёт индекс использовать..
PM WWW   Вверх
-=Ustas=-
Дата 20.9.2006, 12:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ustix IT Group
****


Профиль
Группа: Участник Клуба
Сообщений: 2222
Регистрация: 21.1.2005
Где: Краснодар

Репутация: 4
Всего: 69



Цитата(muzer @  20.9.2006,  11:40 Найти цитируемый пост)
Что "но"? Не вижу ни одного опровержения, посмотрите explain'ы к тем запросам, которые у вас в первом примере, увидите сами.

Я же написал еще в первом посте результаты EXPLAIN.
Цитата(Bikutoru @  20.9.2006,  11:19 Найти цитируемый пост)
лучше использовать тип TIMESTAMP, который обладает возможностью автоматического обновления своего значения.

Нет, я привык с INT  работать.

Вечером буду пробовать запросы переписывать.


--------------------
В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм.
-----
PM WWW ICQ Skype   Вверх
muzer
Дата 20.9.2006, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 387
Регистрация: 31.8.2006

Репутация: 30
Всего: 31



Цитата(-=Ustas=- @  20.9.2006,  13:50 Найти цитируемый пост)
Я же написал еще в первом посте результаты EXPLAIN.

У меня в базах результаты explain'ов для аналогичных вашим запросов получаются логичные, с использованием индекса. Попробуйте написать FORCE INDEX.
PM WWW   Вверх
-=Ustas=-
Дата 20.9.2006, 18:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ustix IT Group
****


Профиль
Группа: Участник Клуба
Сообщений: 2222
Регистрация: 21.1.2005
Где: Краснодар

Репутация: 4
Всего: 69



Цитата(muzer @  20.9.2006,  18:19 Найти цитируемый пост)
У меня в базах результаты explain'ов для аналогичных вашим запросов получаются логичные, с использованием индекса. Попробуйте написать FORCE INDEX. 

Странно, а версия мускула какая?


--------------------
В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм.
-----
PM WWW ICQ Skype   Вверх
Sardar
Дата 20.9.2006, 18:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

Репутация: 1
Всего: 317



Цитата(-=Ustas=- @  19.9.2006,  21:21 Найти цитируемый пост)
    
SELECT * FROM `category` ORDER BY `created`

Цитата(-=Ustas=- @  19.9.2006,  21:21 Найти цитируемый пост)
Ноль реакции, EXPLAIN пишет что кеи не юзаются и using filesort, т.е. понятно что перебирает всю таблицу. 
Делаю такой запрос:

А зачем должен здесь использоваться индекс, если выбираються в прямом смысле все строки. Индекс нужен для быстрого поиска, что бы эффективно/быстро откинуть большинство строк заведомо не подходящие по условию.


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
muzer
Дата 20.9.2006, 19:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 387
Регистрация: 31.8.2006

Репутация: 30
Всего: 31



Sardar, для убыстрения сортировки (индекс-то уже отсортирован). MySQL считает, что затратнее при выборке всех строк идти по индексу и seek'ать данные из файла данных, нежели сортировать их налету при выборке. Спорить с разработчиками mysql'я не берусь, но считаю, что зависит от конкретного случая, кол-ва данных и т.д.

-=Ustas=-, я понял в чём разница, я тестировал учитывая условия вашей задачи, а вы просто абстрактный пример, так вот, если LIMIT добавить, в который написать число меньшее раза в два чем кол-во строк в таблице, то индекс подхватывается без FORCE INDEX, иначе нет.. smile Поведение одинаковое наблюдаю на 4.1.11 и 5.0.22.

PM WWW   Вверх
-=Ustas=-
Дата 20.9.2006, 19:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ustix IT Group
****


Профиль
Группа: Участник Клуба
Сообщений: 2222
Регистрация: 21.1.2005
Где: Краснодар

Репутация: 4
Всего: 69



Хм... счас попробовал под никсами на 5-ой версии мускула, все нормально и молниеностно выполняет. В EXPLAIN правильные ключи отображает smile 
Может быть что у меня на винде корявый мускул стоит?


--------------------
В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм.
-----
PM WWW ICQ Skype   Вверх
-=Ustas=-
Дата 20.9.2006, 19:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ustix IT Group
****


Профиль
Группа: Участник Клуба
Сообщений: 2222
Регистрация: 21.1.2005
Где: Краснодар

Репутация: 4
Всего: 69



Цитата(muzer @  20.9.2006,  19:05 Найти цитируемый пост)
а вы просто абстрактный пример

Да, но суть в реальном запросе не меняется обсолютно.
Цитата(Sardar @  20.9.2006,  18:37 Найти цитируемый пост)
А зачем должен здесь использоваться индекс, если выбираються в прямом смысле все строки

Ну как зачем, для ORDER BY

Вот на винде, версия 4.1.6, 20 тыс записей, запрос:
Код

SELECT * FROM `category` ORDER BY `created` LIMIT 7

В EXPLAIN выдает filesort, сама выборка проходит около 30 сек.

Вот. Этот же самый запрос на никсе, версия 5.хх, 20 тыс записей, запрос абсолютно такой же - в EXPLAIN выдает key - created, время 0.00 sec

Что жу это получается, что гонки на винде?


--------------------
В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм.
-----
PM WWW ICQ Skype   Вверх
Sardar
Дата 20.9.2006, 22:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

Репутация: 1
Всего: 317



Цитата(-=Ustas=- @  20.9.2006,  18:55 Найти цитируемый пост)
Ну как зачем, для ORDER BY

Верно, видно я не выспался...  smile 
Запусти ANALYZE TABLE на таблице, достаточно что бы мускул "увидел" индексы.

Цитата(-=Ustas=- @  20.9.2006,  18:55 Найти цитируемый пост)
Вот. Этот же самый запрос на никсе, версия 5.хх, 20 тыс записей, запрос абсолютно такой же - в EXPLAIN выдает key - created, время 0.00 sec

Может таблица в кеше была, а под виндой чего сложного делалось параллельно...... да мало ли чего может быть smile
Запусти тест раз 50, по идее не должно быть таких разительных различий.


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
-=Ustas=-
Дата 20.9.2006, 23:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ustix IT Group
****


Профиль
Группа: Участник Клуба
Сообщений: 2222
Регистрация: 21.1.2005
Где: Краснодар

Репутация: 4
Всего: 69



Цитата(Sardar @  20.9.2006,  22:41 Найти цитируемый пост)
Запусти ANALYZE TABLE на таблице, достаточно что бы мускул "увидел" индексы.

Запустил smile :
Код

 Table                  | Op      | Msg_type | Msg_text
------------------------+---------+----------+-----------------------------
 database.shop_product | analyze | status   | Table is already up to date

EXPLAIN выдал тодже самое что и до этого.

Цитата(Sardar @  20.9.2006,  22:41 Найти цитируемый пост)
Может таблица в кеше была

Не думаю, сразу после перегрузки пробую.

Цитата(Sardar @  20.9.2006,  22:41 Найти цитируемый пост)
а под виндой чего сложного делалось параллельно...... да мало ли чего может быть 

Тоже мысль такая была, все процессы килял, оставлял только mysqld-nt.

Добавлено @ 23:14 
Наверное переснесу все, по-новой поставлю.

Добавлено @ 23:15 
Посмотрю, что получится smile


--------------------
В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм.
-----
PM WWW ICQ Skype   Вверх
-=Ustas=-
Дата 27.9.2006, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ustix IT Group
****


Профиль
Группа: Участник Клуба
Сообщений: 2222
Регистрация: 21.1.2005
Где: Краснодар

Репутация: 4
Всего: 69



Мужики, такой вопрос. Может чего-то не догоняю... Следуя мануалу, цитаты:
Код

Индекс может также использоваться и тогда, когда предложение ORDER BY не соответствует индексу в точности, если все неиспользуемые части индекса и все столбцы, не указанные в ORDER BY - константы в выражении WHERE. Следующие запросы будут использовать индекс, чтобы выполнить ORDER BY / GROUP BY.

[B]SELECT * FROM t1 ORDER BY key_part1,key_part2,...[/B]
SELECT * FROM t1 WHERE key_part1=constant ORDER BY key_part2
SELECT * FROM t1 WHERE key_part1=constant GROUP BY key_part2
SELECT * FROM t1 ORDER BY key_part1 DESC,key_part2 DESC
SELECT * FROM t1 WHERE key_part1=1 ORDER BY key_part1 DESC,key_part2 DESC

Код

Ниже приведены некоторые случаи, когда MySQL не может использовать индексы, чтобы выполнить ORDER BY (обратите внимание, что MySQL тем не менее будет использовать индексы, чтобы найти строки, соответствующие выражению WHERE):

   [B] * Сортировка ORDER BY делается по нескольким ключам: SELECT * FROM t1 ORDER BY key1,key2[/B]
    * Сортировка ORDER BY делается, при использовании непоследовательных частей ключа: SELECT * FROM t1 WHERE key2=constant ORDER BY key_part2
    * Смешиваются ASC и DESC. SELECT * FROM t1 ORDER BY key_part1 DESC,key_part2 ASC
    * Для выборки строк и для сортировки ORDER BY используются разные ключи: SELECT * FROM t1 WHERE key2=constant ORDER BY key1
    * Связываются несколько таблиц, и столбцы, по которым делается сортировка ORDER BY, относятся не только к первой неконстантной (const) таблице,


Это что, противоречие?! И что здесь в этих примерах подразумавается под key и key_part?
Я сделал аналогично этому:
Код

Индекс может также использоваться и тогда, когда предложение ORDER BY не соответствует индексу в точности, если все неиспользуемые части индекса и все столбцы, не указанные в ORDER BY - константы в выражении WHERE. Следующие запросы будут использовать индекс, чтобы выполнить ORDER BY / GROUP BY.

SELECT * FROM t1 ORDER BY key_part1,key_part2,...
[B]SELECT * FROM t1 WHERE key_part1=constant ORDER BY key_part2[/B]


Т.е. :
Код

CREATE TABLE `test` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `name` varchar(50) collate cp1251_bin NOT NULL default '',
  `title` varchar(255) collate cp1251_bin NOT NULL default '',
  `pid` int(10) unsigned NOT NULL default '0',
  `active` enum('Y','N') collate cp1251_bin NOT NULL default 'N',
  `sort` int(10) NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `pid` (`pid`),
  KEY `sort` (`sort`),
  KEY `active` (`active`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251 COLLATE=cp1251_bin;

Делаю запрос:
Код

EXPLAIN SELECT * FROM test WHERE pid = 5 ORDER BY sort DESC;

И он мне говорит что Using filesort. В чем дело, или я что-то не понимаю?
P.S. Не пинайте сильно, и по возможности, если я не прав, объясните в чем я не прав. Или я неправильно себе представляю работу индексов?!


--------------------
В искаженном мире все догмы одинаково произвольны, включая догму о произвольности догм.
-----
PM WWW ICQ Skype   Вверх
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | MySQL | Следующая тема »


 




[ Время генерации скрипта: 0.0621 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.