У меня есть таблица MESSAGE с 1 млн строк (и растет). Каждый запрос сообщений включает выбор строк WHERE isRequest = True или WHERE isRequest = False, но не обоих одновременно. Подавляющее большинство моих запросов ищут isRequest = False. В эту таблицу пишут очень часто, и мне нужно поддерживать быструю запись (поскольку пользователи любят отправлять сообщения друг другу с малой задержкой). Также обратите внимание, что таблица MESSAGE в настоящее время не имеет индексов столбцов, кроме первичного ключа.
95% строк имеют isRequest = False и только 5% строк имеют isRequest = True. Является ли индексирование логического поля isRequest более производительным в таком сценарии?
Кроме того, я понимаю, что столбцы индексации потребляют память, но эти накладные расходы эквивалентны для всех типы данных столбца, включая, в моем случае, логические значения?
Обновление:
После дальнейшего анализа с @Rick James мы придумали новую схему таблицы ( обратите внимание, что все PK являются автоматическими c, так что относительность времени заметна ):
MESSAGE (id=PK) (sender_id, recipient_id, conversation_id = FKs)
---------------------------------------------------------------
id sender_id recipient_id message conversation_id
1 1 2 "hows it going" 4
2 2 1 "great! hbu" 4
3 1 8 "hey man" 3
4 9 1 "please respond" 2
5 4 6 "goodnight girl" 1
CONVERSATION (id=PK) (userA_id, userB_id = FKs)
-----------------------------------------------
id userA_id userB_id
1 4 6
2 1 9
3 1 8
4 1 2
USERCONVERSATION (id=PK) (userA/B_id, conver_id, lastMsg_id = FKs)
------------------------------------------------------------------
id userA_id userB_id conver_id lastMsg_id isRequest
1 4 6 1 5 False
2 6 4 1 5 False
3 1 9 2 4 True
4 9 1 2 4 True
5 1 8 3 3 False
6 8 1 3 3 False
7 1 2 4 2 False
8 2 1 4 2 False
Индексы:
MESSAGE: index(id),
index(conversation_id, id)
CONVERSATION: index(id),
USERCONVERSATION: index(id),
index(user_id, isRequest),
index(user_id, lastMessage_id),
index(conversation_id)
Запросы в приложении:
Следующие запросы должны выполняться из-за правильной индексации, как указано выше. Свяжитесь с нами, если можно внести улучшения.
Чтобы получить последние 20 разговоров (включая содержимое последнего сообщения и информацию о другом пользователе) для переменной userID:
SELECT T4.userB_id, T4.username, T4.profilePic, T4.conver_id,
T4.message
(
SELECT T1.userB_id, T2.username, T2.profilePic, T1.conversation_id,
T1.lastMessage_id
FROM
(
SELECT userB_id, conversation_id, lastMessage_id
FROM rage.userconversation
WHERE userA_id = {userID}
AND isRequest=False
) AS T1
LEFT JOIN rage.user AS T2 ON T1.userB_id = T2.id AS T3
)
LEFT JOIN rage.message AS T4 ON T1.lastMessage_id = T4.id
ORDER BY T4.id DESC
LIMIT 20
Word объяснение: Получите 20 самых последних строк USERCONVERSATION, поскольку там хранится последнее сообщение. Чтобы найти 20 самых последних для данного пользователя, выберите все строки с user_id = userID и отсортируйте их по lastMessage_id DES C. Это верно, потому что message_id увеличивается автоматически. Наряду с последним сообщением нам нужно получить некоторые пользовательские данные (изображение профиля, имя пользователя) другого пользователя в разговоре. Мы достигаем этого путем присоединения слева.
Результат:
RESULT (for userID = 1)
---------------------------------------------------------------
userB_id username profilePic message conver_id
8 John 8.jpg "hey man" 3
2 Daisy 2.jpg "great! hbu" 4
Затем, когда пользователь нажимает на беседу, поскольку у нас есть chat_id, мы просто:
SELECT * FROM rage.message WHERE conversation_id={conver_id} ORDER BY id DESC LIMIT 20
Надеюсь, с тех пор, как мы проиндексировали (dialog_id, id), сортировка стала быстрой.