Питання про реляційних субд, на які ніколи не вистачає часу

Вступ
Волею доль, я працюю в enterprise близько 5 років, за цей час набрався пул питань про реляційних базах даних, і вони регулярно спливають у голові перед сном.

Але з'ясовувати докладні відповіді на них дорого з часу, бо відправляють в чудесну країну багатотомних мінлива, лінгвістики & статистики і товстих книг.

Прошу допомоги у спільноти у викоріненні свого і чужого невігластва.
Примітка: відповіді на більшість питань були висвітлені в цієї статті, але розкриті не повністю.

Свої емпіричні припущення заховаю під кат.

Запитання
  1. Що відбувається в субд при розмірі таблиці+кеш+індекси << оперативної пам'яті?

    Припущення і нові питанняЛогіка і деякий досвід підказують, що якщо у бази у налаштуваннях вказано розмір менше оперативної пам'яті, і в системі є достатньо пам'яті для її розміщення — база повинна укластися повністю в оперативку, але, т. к. ACID вимагає узгодженість і довговічність повинна відбуватися фіксація на диск, хоча б через підсистему логів. Чи Так це насправді? Якщо не так — можна налаштувати субд таким чином, щоб читання завжди здійснювалося з оперативної пам'яті?

  2. Якщо розмір таблиці >> оперативної пам'яті, а індексу по ній немає(або ми в нього не потрапляємо) як менеджер пам'яті визначає, яке кількість місця може зайняти під вибірку з таблиці?

    ПрипущенняКількість необхідного місця можна спробувати знайти статистично, з розподілу значень всередині колонок( в підсистемі статистики субд зазвичай є такі дані.).
    Кількість доступної пам'яті, можна порахувати по середньої навантаженні за останній час, і знайти очікуване кількість вільного місця.

  3. Як і куди здійснюється почергова вибірка записів таблиці(і звідки, пам'ять/диск) для фільтрації? Які при цьому відбудуться блокування (для бд з версионированием записів і без)?

    Припущення
    • Швидше за все, є фасад єдиного менеджера пам'яті, який в змозі висмикнути значення з кешу/індексу, і якщо його там немає — взяти з диска.
    • Напевно, він має чергу опрацювання запитів на отримання рядків. Напевно, порядок архітектури: оптимізатор запитів, визначає звідки вибираємо значення — таблиця/індекс, менеджер, визначає де індекс/таблиця — в пам'яті або на диску, кеш — є там рядки індексу/таблиці з заданим ідентифікатором, підтягування потоком в пам'ять індексу/таблиці, прогін потрібної частини індексу/таблиці через оперативку з вибіркою потрібних значень.

    • Куди — швидше за все, окремий пул пам'яті процесу, якщо місця немає — ос або самі мапим його на диск

  4. Що станеться, якщо розмір відповідної вибірки >> оперативної пам'яті? Які бази вміють віддавати дані потоком вході вибірки, а які — тільки за повної готовності вибірки? Можна налаштувати поведінку?

    Припущення і нові питання
    • Блокування будуть, безумовно, залежатиме від налаштувань необхідної узгодженості бд(wiki, Уровень_изолированности_транзакций).
    • Питання, на який у мене все-таки немає легкої відповіді — чи можуть рядка змінюватися при читанні великого обсягу, незважаючи на потік читання? Це буде підпадати під ситуацію «брудного читання»? Що станеться, якщо інша транзакція намагається змінити рядок, яку ми зараз читаємо? Є читання транзакцією, яка може блокувати інші транзакції? При версионировании рядків все простіше — читаємо рядки з версією = остання закоммиченная на момент старту читання

    • Теоретично, повинна укладати на диск засобами бд/ос

  5. Як оптимізатор запитів формально доводить еквівалентність умов в реченні ON для JOIN-запиту і пропозиції WHERE цього запиту? Приклад під катом.

    Приклад і припущення
    • pg неодноразово помічав відсутність різниці в продуктивності і плані запитів

      select * from a 
      inner join b 
      on a.id = b.id 
      where a.n > N and b.n <N
      
      та
      select * from (select * from a where a.n > N) as a
      inner join (select * from b where b.n <N ) a b 
      on a.id = b.id 

    • Навіть для більш складних запитів, де умови були дещо «вище» в дереві побудови запитів pg якимось чином доводив еквівалентність і вибирав на join не весь обсяг даних, а тільки підходить під вибірку.
    • тобто є якийсь мехнизм поширення умов вибірки по дереву запитів. MS-SQl 2008 вів себе гірше і показував суттєву різницю у часі проходження запитів. Чому?
      Якими методами з логіки/програмування можна довести еквівалентність on і where?
      Коли і де це працює?

  6. Як відбувається робота з індексом більш ніж одному полю? Як відбувається робота з b-tree індексом, якщо він не влазить в оперативну пам'ять? Через віртуальну пам'ять ос? Чи є спосіб завантажувати індекс частково?

    З чим пов'язане питанняМені не вдається зрозуміти, як організовано b-tree, коли колонок в індексі > 1 і вони різних типів. Логічне припущення — ключем дерева є деяка хеш функція від колонок, але тоді явно вимагається дотримання умови, що
    H(a,b) > H(a) & H(a,b) > H(b) & H(a,b) < H(a +1, b) & H(a, b+1) < H(a+1)
    я здогадуюся, що з цим може допомогти перцептивний хеш з деякими «розрядами», де розряд відповідає колонці, але мене бентежить довжина хеша.
    Іншим варіантом бачиться мені не робити хеш, а явно порівнювати значення полів індексу при завантаженні/вивантаженні з нього. Але тоді не зрозуміло, як спрацює

    select * from A 
    where A. b > 1 A. c < 3
    
    якщо індекс оголошено
    <A. a, A b, A. c>
    Як ми будемо обходити дерево не маючи обмеження по першому рівню?
    Буде планувальник використовувати цей індекс?
    Пов'язані питання — чи має значення порядок перерахування полів індексу в умові WHERE?
    Чи ми зможемо потрапити в індекс, якщо частина полів перераховано в реченні ON подзапроса, а частина в WHERE більш загального запиту, тобто працює перерозподіл умов разом з оцінкою потрапили/не потрапили в індекс?
    Як на це можна вплинути?

    Більш спеціалізовані питання, на які також важко дається відповідь.

    1. За яких умов варто робити таблицю партиционированной?
    2. Коли партіцій занадто багато?
    3. На якому розмірі варто задуматися про шардировании?
    4. Коли нормалізувалася, а коли денормализовывать схему даних?
    5. На якій довжині рядка і чому саме на такій багато бд виносять її в окреме сховище?
    6. Чому в pg використання CTE в запитах значно швидше реалізації з тимчасової таблицею? Чи це Так? Якщо так — чи є винятки?
    Пояснення

    Я радий був би знайти подібні відповіді сам, але більша частина питань тоне під потоками флуду, або ховається глибоко в документації/исходниках великих проектів. Відповіді з коментарів будуть додані до відповідних питань. Що зможу — постараюся знайти сам.

    Дякуємо за розуміння.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.