SQLinfo.ru - Все о MySQL

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

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

Вы не зашли.

#1 24.01.2010 02:32:41

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

сортировка большого словаря (id - varchar)

Имеется словарь на несколько миллионов строк:

CREATE TABLE `words` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `word` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `word` (`word`)
) ENGINE=MyISAM AUTO_INCREMENT=6958803 DEFAULT CHARSET=cp1251


Весь он никогда не нужен. Но иногда бывают ситуации, когда надо несколько тысяч строк. Вернее, все несколько тысяч тоже не нужны; из них нужны первые несколько десятков, но первые по алфавиту, т.к. запрос вида
WHERE id IN (тут несколкько тысяч) ORDER BY word)

Вот от ORDER BY word на нескольких тысячах ему становится плохо, т.к. приходится (как я понимаю) все их выбрать, а потом отсортировать. Работает порядка минуты (медленная стадия, как я понимаю - выборка).

Можно ли тут как-то ситуацию улучшить?
Не поможет ли составной ключ на id и небольшой кусок строки вида KEY (id, word(4) ) ?
Может быть, стоит перенести в память?

Неактивен

 

#2 24.01.2010 22:52:34

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

Re: сортировка большого словаря (id - varchar)

А тебе и правда нужен id?

Разумеется, нужен ключ на (id, word). И, если уникальность поддерживаешь
с помощью базы, остальные два тоже нужны sad

Неактивен

 

#3 27.01.2010 12:23:09

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: сортировка большого словаря (id - varchar)

А тебе и правда нужен id?

Да, т.к. надо хранить обращения к словам.

Подумал тут, что можно сделать ключ на (id, word(1)). У одной буквы (грубо говоря) CARDINALITY около 30.
У меня проблемы возникают, когда надо вытащить ~1000 слов и больше. Если это количество уменьшить в 30 раз, то получится, в принципе, приемлемое значение
(это если он до выборки догадается отсортировать по индексу и LIMIT уже применть к проиндексированному, а не лезть в данные и только потом отсекать по LIMIT)

(хотя, может быть, эта проблема отпадет, т.к. вот)

Неактивен

 

#4 27.01.2010 12:30:41

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

Re: сортировка большого словаря (id - varchar)

Странно, что долго сортируется 1000 слов. Может быть плохая сама конструкция id IN (тысяча). Нельзя ли ее поменять на JOIN с временной таблицей?

Неактивен

 

#5 27.01.2010 13:03:06

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: сортировка большого словаря (id - varchar)

Там дело не в самой сортировке, а в том, что надо сначала их все 1000 вытащить (таблица длинная, поэтому долго очень). А это обидно, т.к. из тысячи мне нужны 20. И если б он сначала сортировал, то вытаскивал бы 20, а не 1000.

Неактивен

 

#6 27.01.2010 13:07:36

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

Re: сортировка большого словаря (id - varchar)

Слова произвольные и нужно только 20? Можно пробовать делать AND word < 'бука', тогда точно будет отсекать. Если получится меньше 20, то повторить запрос.

Неактивен

 

#7 27.01.2010 16:13:07

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: сортировка большого словаря (id - varchar)

Вообще идея дерзкая.. Но, боюсь, слишком неравномерным может оказаться распределение слов.
Короче. Лучше структуру базы оптимизировать, чем мы уже занимаемся в соседней теме.

Неактивен

 

#8 20.02.2010 06:04:53

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: сортировка большого словаря (id - varchar)

Вопрос для ясности.

Запрос вида

WHERE id IN (много) или JOIN USING(id)
ORDER BY text
LIMIT X,Y

будет использовать ключ (id, text(N)) для LIMIT или будет вытаскивать все записи, соответствующие WHERE, а потом на них делать LIMIT?

Неактивен

 

#9 20.02.2010 10:07:18

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

Re: сортировка большого словаря (id - varchar)

Он знает список id, по любому id может выбирать последовательно в порядке возрастания text. Если сделать ORDER BY id,text, то тогда принципиально можно использовать ключ (но в данной задаче это бесполезно). В текущей постановке нужно делать сортировку отдельно (будет filesort).

Неактивен

 

#10 20.02.2010 20:21:33

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: сортировка большого словаря (id - varchar)

Он знает список id, по любому id может выбирать последовательно в порядке возрастания text.

Так а почему он тогда не может остановить выборку, набрав нужное количество значений?

Неактивен

 

#11 20.02.2010 21:22:04

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

Re: сортировка большого словаря (id - varchar)

Вот ты взял id1 и его текст, затем id2 и его текст, потом id3 и его текст. Пусть у меня LIMIT 3 и я остановил выборку. Она получилась неотсортирована по полю text. А чтобы отсортировать, нужно выбрать сначала text для всех id, а потом выполнить filesort.

Вот пример. У тебя есть телефонный справочник (Фамилия, Имя, телефон) и ключ на нем (Фамилия, Имя). То есть отсротирован по Фамилии и в рамках каждой Фамилии по имени. Я тебе даю список фамилий (Скворцов, Дьяконов, Денисов, Иванов, Карпов, Станиславский, Тверской, Губкин) и прошу выбрать первые три в списке, остортированном по имени. Тебе придется найти их всех, а потом сортировать по имени.

Вот если бы я просил сортировку по Фамилии и Имени, то другое дело. Берем первую Фамилию и последовательно по Именам проходим и.т.д., останавливаем, когда набрали нужно количество записей. А тебе нужна сортировка, которой нет в индексе.

Неактивен

 

#12 21.02.2010 00:32:23

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: сортировка большого словаря (id - varchar)

тебе нужна сортировка, которой нет в индексе.

Как же нет?
У меня индекс не только на Фамилию, но и на часть Имени.

Скворцов А
Дьяконов М
Денисов П
Иванов А
Карпов В
Станиславский Д
Тверской Б
Губкин П

Здесь же понятно, что первые три по имени - это Скворцов, Иванов и Тверской. Зачем лезть для всех восьмерых в базу, если известно, что понадобятся только три?

Или MySQL не может использовать для сортировки правую часть индекса?

Неактивен

 

#13 21.02.2010 11:53:50

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

Re: сортировка большого словаря (id - varchar)

В твоем примере как раз непонятно. Может быть Скворцовых несколько на букву А. Все равно ты сейчас сделал не операцию над индексом, а выбрал из индекса данные и сделал над ними filesort.

Операция над индексом это следующее.
а. Найти первую запись с минимальным значением индекса >= заданной константе
б. Найти следующую запись в порядке следования индекса

То, что ты предлагаешь, это некий хитрый алгоритм, который делает filesort сначала используя неполную информацию из индекса, а потом уже корректирует используя выборку данных. Такой алгоритм в MySQL не реализован.

Неактивен

 

Board footer

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