Дизайн бази даних для отримання непрочитаної статті в mysql (таблиця рядка понад 100M) - mysql, sql, database, database-design, mariadb

Ця інформація дуже стисла.

Є 2 таблиці.

стаття

-----------------------------------
|id | weight | text               |
-----------------------------------
|1  | 10     | blah               |
|2  | 100    | blah               |
|3  | 50     | blah               |
|4  | 1000   | blah               |
-----------------------------------

читати

-----------------------------------
| user_id | article_id            |
-----------------------------------
| 1       | 4                     |
| 1       | 2                     |
| 1       | 3                     |
| 2       | 3                     |
| 2       | 4                     |
-----------------------------------

Я хочу отримати непрочитані статті за допомогою запиту нижче (дуже стисло)

SELECT
a.*
FROM
article a LEFT OUTER JOIN read r ON r.article_id = a.id and r.user_id = 1
WHERE
r.id IS NULL
ORDER BY
a.weight DESC
LIMIT 10

важлива інформація

  1. Кількість read table рядків зберігається менше 1000 на користувача. (видалити старі дані)
  2. колонка ваги в таблиці статті часто змінюється. (Це означає, що замовлення не зафіксоване)

проблема .. (коли кількість користувачів: понад 1M)

  1. спосіб отримання непрочитаних статей за допомогою таблиці читання (не в, зовнішнє з'єднання не важливо)
    • число read table рядки будуть над 1G

Він працює добре (поточний номер рядків читання таблиці: 100M). але я повинен підготувати наступний крок, тому що кількість користувачів швидко зростає.

Який найкращий спосіб для великих послуг у цьому випадку?

(sharding? таблиця перегородки? або редизайн архітектури?)

Спасибі заздалегідь

Відповіді:

0 для відповіді № 1

Проблема полягає в тому, щоб використовувати індекс, наскільки це можливо.

SELECT a.*
FROM  a
LEFT JOIN read r
ON r.article_id = a.id and r.user_id =1
WHERE r.id IS NULL
ORDER BY a.weight DESC
LIMIT 10

Редагувати: Занепокоєння для вас - це розмір даних read таблиці і ми повинні зменшити розмір даних. Для цього у нас є кілька варіантів:

  • Розділи MySQL: створюйте розділи на діапазоні user_id (можуть бути 100K користувачів на розділ
  • Створіть кілька таблиць: Подібно до розділів, але ви будете мати дані в різних базах даних (навіть на різних серверах БД). Виходячи з user_id, ви будете приймати рішення щодо приєднання таблиці / бази даних.

Крім того, ви можете подумати про наявність архівних даних старих даних періодично, і програма повинна бути достатньо розумною, щоб вирішити, чи потрібно запитувати архівні таблиці або живу таблицю.


0 для відповіді № 2
  • Додайте стовпець до article. Це буде прапор, що говорить про те, чи стаття прочитана / не прочитана. (Не вказуйте на кількість користувачів або мітку часу, що уповільнює подальші кроки.)
  • Всякий раз, коли користувач читає статтю, перевірте прапор і змініть його, якщо це необхідно.
  • Have `INDEX (прапор, вага, id) - це дозволить виконати ваш запит майже миттєво. Це повинно бути нормально на цій таблиці з мільйонами рядків.

Проблема:Оскільки ви очищаєте (після 1000), деякі "прочитані" статті можуть стати "непрочитаними". Щоб вирішити цю проблему, виконайте пакетну очистку і зібрати окремий список статей, які було очищено. Тоді виконайте стомлюючу задачу повторного обчислення прапора, але тільки для цих статей. INDEX(article_id) допоможе; використання EXISTS ( SELECT * FROM read WHERE article_id = $aid ). (Можливо, це може бути перетворено на пакетну операцію, а не на одну допомогу одночасно.)

Ще одна проблема: вторинні ключі таблиць з мільярдами рядків коштують дорого - вони можуть призвести до великої кількості вводу-виводу. Перш ніж спробувати вирішити цю проблему, вкажіть, будь ласка SHOW CREATE TABLE для обох таблиць, а також для будь-яких інших загальних SELECTs. Вибір правильного індексу (ів) і типів даних становить дуже Важливе значення для виконання в таблицях, що складаються з мільярдів рядків ..


Схожі запитання
Найбільш популярний