Ребята, у меня вопрос. Есть столбец item (varchar(10)) в ut8mb4 табличке (innoDb).. записей в таблице может быть много, реально сотни тысяч но разных значений в этом столбце максимально может быть 5-6.. делаю по этому полю индекс... если допустим индекс будет не на 10 символов, а на 3...это ускорит поиск или пофиг 10 или 3?? и может лучше использоваться связь "один ко многим"? одна табличка с значениями и автоинкрементным столбцом.. а вторая табличка просто ид этих значения.. ну и плюс связать может эти таблички foreign ключами? что будет более производительно?? --- Добавлено --- хотя пока писал понял что наверно один ко многим будет лучше.. и индексы меньше занимать будут и табличка сама будет меньше занимать.. плюс внешние ключи тоже могут облегчить жизнь..
когда записей за миллион, приходится историю чистить)) начинает чуть чуть тупить.. в медленных запросах мускула видно.. это больше для меня сейчас гипотетический вопрос чем практический)) на практике я раз в полгода чищу просто таблицу от старых записей)
PHP: CREATE TABLE IF NOT EXISTS `smf_kpr_grades` ( `id` int(10) NOT NULL AUTO_INCREMENT, `item` varchar(10) NOT NULL DEFAULT 'message', `item_id` int(10) NOT NULL, `grade` int(10) NOT NULL, `grade_author` int(10) NOT NULL, `grade_time` int(10) NOT NULL, PRIMARY KEY (`id`), KEY `idx_item_and_item_id_and_author` (`item`,`item_id`,`grade_author`), KEY `grade_time` (`grade_time`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=25090364 ; а запрос или это PHP: $request = $smcFunc['db_query']('', ' SELECT k.grade, k.grade_author, IFNULL(mem.real_name, 0) AS grader, mg.online_color FROM {db_prefix}kpr_grades AS k LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = k.grade_author) LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = mem.id_group) WHERE k.item = {string:type} AND k.item_id = {int:id} ORDER BY k.grade_time', array( 'type' => 'message', 'id' => $itemID, ) ); или этот PHP: $request = $smcFunc['db_query']('', ' SELECT m.id_msg, k.grade FROM {db_prefix}messages AS m LEFT JOIN {db_prefix}kpr_grades AS k ON (k.item_id = m.id_msg AND k.item = {string:type}) WHERE k.item = {string:type} AND k.item_id BETWEEN {int:first} AND {int:last} AND k.grade_author = {int:user} AND m.id_topic = {int:topic}', array( 'type' => 'message', 'topic' => $context['current_topic'], 'first' => $context['first_message'], // id первого сообщения на текущей странице темы 'last' => $context['topic_last_message'], 'user' => $context['user']['id'], ) ); на данный момент таблица не сильно забита и поэтому не могу сказать точно.. П.С. Да ошибся.. табличка не в innoDB а MyISAM
В первую очередь выбросить этого динозавра. А точно ли item дает лучшую селективность, чем item_id? Если нет, то поменять местами. И вообще, возможно будет лучше создать несколько индексов, нужно пробовать и смотреть план выполнения запроса.
первый запрос должен работать быстро. если работает медленно, то смотри, чтобы были индексы. Его можно сделать без джоинов, а зависмые сущности выбрать после по собранным ключам. второй запрос можно денормализовать. за каким хреном вообще грейд сообщения хранится в другой таблице?