[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Как верно расставить индексы. Объясните...
Страницы: 1, 2, 3, 4
inpost
Всем привет.
Есть таблица с переписками:

CREATE TABLE IF NOT EXISTS `mess_sett` (
`id` int(10) unsigned NOT NULL,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`subject` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`prew` text COLLATE utf8mb4_unicode_ci NOT NULL,
`man_id` int(10) unsigned NOT NULL,
`man_where` enum('inbox','outbox','') COLLATE utf8mb4_unicode_ci NOT NULL,
`man_group` tinyint(1) NOT NULL DEFAULT '0',
`man_saw` tinyint(1) NOT NULL DEFAULT '0',
`girl_id` int(10) unsigned NOT NULL,
`girl_where` enum('inbox','outbox','') COLLATE utf8mb4_unicode_ci NOT NULL,
`girl_group` tinyint(1) NOT NULL DEFAULT '0',
`girl_saw` tinyint(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

ALTER TABLE `mess_sett`
ADD PRIMARY KEY (`id`), ADD KEY `read` (`man_id`,`man_group`,`man_where`);


Размер таблицы: 20 млн. записей (10 гб. данных). Планируется за пару лет увеличение х2 объема

Есть стандартная выборка:
SELECT `id`,`subject`,`prew`,`man_saw`,`girl_id`
FROM `mess_sett`
WHERE `man_id` = ".(int)$_SESSION['user_data']['id']."
AND `man_where` = '".es($GET['sel'])."'
AND `man_group` = ".(int)$GET['id']."
ORDER BY `date` DESC


А теперь есть дополнительные выборки с сортировками(!):
ORDER BY `girl_id` ASC/DESC
ORDER BY
`man_saw` ASC/DESC
ORDER BY
`date` ASC/DESC


Ещё есть поиск внутри раздела по пользователю:
WHERE `man_id` = ".(int)$_SESSION['user_data']['id']."
AND `man_where` = '".es($GET['sel'])."'
AND `man_group` = ".(int)$GET['id']."
AND `girl_id` = "ТУТ ID"


Беру МАКСИМУМ, это самые активные пользователи, у других активность в 2-3 раза ниже:
Запрос по умолчанию по man_id вернёт около 1500-2500 переписок.
Если к запросу добавляем `man_group` (тут подразумевает, что переписки можно блокировать/банить/удалять), то записей становится около 1000-2000.
Если к запросу добавляем `man_where` в итоге сокращается количество записей до 980-1950 (всего настоящих переписок может быть до 50-и, остальное идёт как спам во входящих). outbox - это обозначение, когда переписка в отправленных находится.
__________________________________________________________

Теперь то, что мне до сих пор не ясно, как верно расставить индексы в данной таблице.

Начинаем разбор по порядку, обязательно из 10 млн. остаются 1 тысячу - это индекс man_id. Дальше начинается путаница.
1) Стоит ли использовать индекс для man_group, ведь мы объем выборки сокращаем лишь в 2 раза с 1000 до 500, с 2000 до 1500 или 1000 записей.
2) Стоит ли вообще индекс писать по полю `man_where` ? Если у нас открыта вкладка входящие, то вернутся все те же записи за исключением 10-15 из 1000, а если открыть отправленные, то там 990, каких-то 10 записей отсеяли, разве это те объемы, когда индекс вообще нужен?
3) Как поступить с поиском? Как видим, что поиск идёт по 3-м полям, это значит нам нужны 3 отдельных составных индекса, в каждом из которых дублировать `man_id`,`man_where`,`man_group` и 4-ым добавлять поле, по которому идёт ORDER BY ? Конечно, сортировка пары тысяч строк накладная операция, но на сколько это разумно в данном случае? К этому пункту стоит добавить то, что в сутки в этой таблице появляется около 200-300 тысяч записей, значит индексы ВСЕ будут перестраиваться постоянно, а это значит, что злоупотребление индексами только навредит Мускулу.
4) По умолчанию используется поиск по дате ORDER BY `date` DESC, им пользуются все, а вот другими сортировками уже редко. Может это тоже взять во внимание и добавить индекс ТОЛЬКО один по `date` ? А остальные варианты сортировки будут пользоваться этим же индексом частично ?
5) Последний запрос идёт man_id + girl_id + man_where + man_group. Учесть это нужен ли тут индекс по man_where/man_group ? Мне кажется, что если вернёт man_id +girl_id лишь 1 запись, то 2 других поля не нужны, они, собственно, нужны в том случае, если письмо находится в другом разделе, а я ищу его по этому разделу. Может вообще выборку сделать по man_id + girl_id БЕЗ man_where/man_group, а эту проверку переложить на PHP ? Благо тогда можно было легко вывести текст "в данном разделе не найдено, зато эта переписка находится в таком-то разделе!".

Пока все рассуждания писал, уже, вроде, и с 5-ым пунктом разобрался. А вот как поступать с сортировкой в данном случае? Собственно вопросы следующего плана "как сделать, и почему сделать именно так".
П.С. Хотелось бы не только понять какой из подходов лучше, но и почему.

_____________
Обучаю веб-программированию качественно и не дорого: http://school-php.com
Фрилансер, принимаю заказы: PHP, JS, AS (видео-чаты). Писать в ЛС (Личные сообщения на phpforum).
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.