Задавайте вопросы, мы ответим
Вы не зашли.
Нужно выбирать данные из некоторой таблицы с разными видами сортировок, привожу примеры запросов:
C cортировкой по дате:
select sql_calc_found_rows b.bandid, b.name, b.ename, b.intdate, b.comments, b.gname, b.gename
from bands b where b.status=0 order by b.dateadd desc limit 0, 30
C cортировкой по количеству:
select sql_calc_found_rows b.bandid, b.name, b.ename, b.intdate, b.comments, b.gname, b.gename
from bands b where b.bandstatus=0 order by b.comments desc limit 0, 30
C cортировкой по алфавиту:
select sql_calc_found_rows b.bandid, b.name, b.ename, b.intdate, b.comments, b.gname, b.gename
from bands b where b.bandstatus=0 order by find_in_set(b.firstchar, '9,8,7,6,5,4,3,2,1,0,z,y,x,w,v,u,t,s,r,q,p,o,n,m,l,k,j,i,h,g,f,e,d,c,b,a,я,ю,э,ь,ы,ъ,щ,ш,ч,ц,х,ф,у,т,с,р,п,о,н,м,л,к,й,и,з,ж,ё,е,д,г,в,б,а') desc, b.firstchar limit 0, 30
Запросы выполняются примерно 900-1100 мс
В таблице около 100000 записей.
Кроме выбираемых в таблице еще довольно много текстовых полей.
Индекс на bandstatus создан составные ключи на status и поля по которым сортировка не использовались.
Планы запросы для выборок с разными сортировками одинаков:
План запроса:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE b ref status status 1 const 52723 Using where; Using filesort
Более подробно раскрыть структуры таблицы не могу. Хотелось бы получить хотя бы общий совет:
1) Можно ли как то заставить сортироватся по составным индексам
2) Имеет ли смысл нормализация и вынесении в отдельную таблицу текстовых полей, которые тут не используются
Неактивен
Сортировка по алфавиту отвратительная, сортируйте просто по firstchar.
Список индексов таки покажите
Скорее всего, индекса по (status, dateadd) хватит.
Неактивен
Добавил ключ на bandstatus и dateadd
Теперь запрос с сортировкой по dateadd идет меньше 100 мс что нормально.
Запрос с сортировкой по comments идет 500 мс
И с сортировкой по алфавиту более 1000 мс
Сортировка по алфавиту с использованием find_in_set обязательна по условию задачи.
План для сортировки по алфавиту:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE b ref status,status_dateadd status_dateadd 1 const 48483 Using where; Using filesort
Результат show keys:
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
bands 0 PRIMARY 1 bandid A 78255 (null) BTREE (null)
bands 1 status 1 bandstatus A 1 (null) BTREE (null)
bands 1 dateadd 1 dateadd A 78255 (null) BTREE (null)
bands 1 firstchar 1 firstchar A 96 (null) BTREE (null)
bands 1 comments 1 comments A 1 (null) BTREE (null)
bands 1 status_dateadd 1 bandstatus A 1 (null) BTREE (null)
bands 1 status_dateadd 2 dateadd A 78255 (null) BTREE (null)
Также показывают типы данных:
Field Type Null Key Default Extra
comments int(11) NO MUL 0 (null)
dateadd int(11) NO MUL 0 (null)
bandstatus tinyint(4) NO MUL 2 (null)
firstchar char(1) NO MUL (null) (null)
Отредактированно pt81 (30.12.2009 18:56:37)
Неактивен
Я вижу что у ключа banstatus cardinality 1 в тоже время при использовании составного ключа status_dateadd используется только один символ из него.
Может ли ключ по статусу быть бесполезным.
upd: Нет убирать индекс с status не удастся все вообще тормозит и идет выборка - "ALL"
Распределение значений в столбце bandstatus:
bandstatus сnt
0 52948
1 17177
2 5824
3 51
Отредактированно pt81 (30.12.2009 19:46:54)
Неактивен
Добавил индексы по status_comments и status_firstchar
теперь план запроса с сортировкой по алфавиту такой:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE b ref status,status_dateadd,status_comments,status_firstchar status 1 const 55287 Using where; Using filesort
C cортировкой по comments:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE b ref status,status_dateadd,status_comments,status_firstchar status_comments 1 const 55287 Using where
C cортировкой по dateadd
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE b ref status,status_dateadd,status_comments,status_firstchar status_dateadd 1 const 55287 Using where
Для сортировки по comments и dateadd составной ключ видит а для сортировки по алфавиту нет.
Изменять порядок столбцов в индекс пробывал, что то вроде dateadd_status работает еще хуже.
Остаются ли какие то выходы, кроме того как облегчит все это дела, вынесением текстовый столбцов из этой таблицы?
Отредактированно pt81 (30.12.2009 20:28:12)
Неактивен
pt81 написал:
Изменять порядок столбцов в индекс пробывал, что то вроде dateadd_status работает еще хуже.
Как использовать составные ключи, в каких случаях они работают?
См. http://sqlinfo.ru/forum/viewtopic.php?id=151
pt81 написал:
Для сортировки по comments и dateadd составной ключ видит а для сортировки по алфавиту нет.
И не будет, так как вы используете find_in_set.
Если над индексируемым полем проводится какая-нибудь операция, то индекс не используется. Напрример:
SELECT .... WHERE 2*field=val; -- индекс по полю field использован не будет
SELECT .... WHERE field=val/2; -- индекс по полю field будет работать.
Вы можете создать дополнительное поле, в котором хранить результат вашего find_in_set и уже по нему делать составной индекс.
Неактивен
Варианты с отдельным полем и другими попытками избавитcя от find in set в order by я пробывал и они мне по тем или иным причинам не подошли.
Кроме того и сортивка с индексом status_dateadd по дате например, все равно использует только часть индекса - Extra
status_dateadd и работают ~300-500 мс что не мало. Думаю надо выносить в отдельную таблицу текстовые поля которые чаще всего не нужны в выборке их около 10-ти типа TEXT и VARCHAR(200) скорее всего из-за них и тормозит на 100000 записей..
Отредактированно pt81 (31.12.2009 18:33:27)
Неактивен