ЁЯПл The SchoolтА║ЁЯЧДя╕П DatabasesтА║ЁЯПЫя╕П рдзрдбрд╛ 18 тАФ OLTP рд╡рд┐рд░реБрджреНрдз OLAP: office рдЖрдгрд┐ рд╕рдВрдЧреНрд░рд╣рд╛рд▓рдп
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯПЫя╕П рдзрдбрд╛ 18 тАФ OLTP рд╡рд┐рд░реБрджреНрдз OLAP: office рдЖрдгрд┐ рд╕рдВрдЧреНрд░рд╣рд╛рд▓рдп

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 18 рдкреИрдХреА рдзрдбрд╛ 18 тАФ рд╢реЗрд╡рдЯрдЪрд╛ рдзрдбрд╛! ┬╖ рдорд╛рдЧреАрд▓: lesson-17-app-code

рднрд╛рдЧ 3 тАФ рдЕрдзрд┐рдХ рдЦреЛрд▓рд╛рдд. рдзрдбреЗ 01тАУ12 рдиреА рд░реЗрдХреЙрд░реНрдб рд░реВрдо рдмрд╛рдВрдзрд▓реА рдЖрдгрд┐ рдЪрд╛рд▓рд╡рд▓реА. рдзрдбреЗ 13тАУ18 рд╣реЗ interviews рдЖрдгрд┐ incidents рдордзреНрдпреЗ рд╡рд┐рдЪрд╛рд░рд▓реЗ рдЬрд╛рдгрд╛рд░реЗ рд╡рд┐рд╖рдп рдЖрд╣реЗрдд тАФ рдкреНрд░рддреНрдпреЗрдХ рддреНрдпрд╛рдЪ school.db рд╡рд░ рдкреНрд░рддреНрдпрдХреНрд╖ рдЪрд╛рд▓рддреЛ.


ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ

рд╕рдВрдкреВрд░реНрдг рдХреЛрд░реНрд╕, рдЖрдгрд┐ db/demo.py рдордзрд▓реЗ olap(): рд╣рдЬреЗрд░реАрдЪрд╛ рдорд╛рд╕рд┐рдХ report, рдЪрд╛рд▓реВ 200,000-рдУрд│реАрдВрдЪреНрдпрд╛ table рд╡рд░ рдЖрдгрд┐ "nightly ETL" рдиреЗ рдмрдирд╡рд▓реЗрд▓реНрдпрд╛ summary table рд╡рд░ рдЪрд╛рд▓рд╡рд▓реЗрд▓рд╛, рдЖрдгрд┐ grade_changes рдордзреНрдпреЗ рдкреНрд░рддреНрдпреЗрдХ рд╢реНрд░реЗрдгреА-рдмрджрд▓ рдиреЛрдВрджрд╡рдгрд╛рд░рд╛ рдПрдХ trigger (change data capture).

ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ

рд╢рд╛рд│реЗрдЪреЗ office рджрд┐рд╡рд╕рднрд░ рдЫреЛрдЯреНрдпрд╛ рдХрд╛рдорд╛рдВрдд рд╡реНрдпрд╕реНрдд рдЕрд╕рддреЗ: рдХрддрд░рд┐рдирд╛рдЪреА рд╣рдЬреЗрд░реА рд▓рд╛рд╡рд╛, рд░реЛрд╣рдирдЪреА рд╢реНрд░реЗрдгреА рджреБрд░реБрд╕реНрдд рдХрд░рд╛, рджрд┐рдпрд╛рдЪреЗ рдирд╛рд╡ рдиреЛрдВрджрд╡рд╛. рд╣реЗрдЪ OLTP тАФ online transaction processing.

рд╡рд░реНрд╖рд╛рддреВрди рдПрдХрджрд╛ рдореБрдЦреНрдпрд╛рдзреНрдпрд╛рдкрд┐рдХрд╛ рдПрдХ рдкреНрд░рдЪрдВрдб рдкреНрд░рд╢реНрди рд╡рд┐рдЪрд╛рд░рддрд╛рдд: "рд╢рд╛рд│рд╛ рд╕реБрд░реВ рдЭрд╛рд▓реНрдпрд╛рдкрд╛рд╕реВрди рдкреНрд░рддреНрдпреЗрдХ рд╡рд░реНрд╖рд╛рдЪреА, рдорд╣рд┐рдиреНрдпрд╛рдиреБрд╕рд╛рд░ рд╣рдЬреЗрд░реА". рд╣реЗ office рд▓рд╛ рд╡рд┐рдЪрд╛рд░рд▓реЗ, рддрд░ рдХрд╛рд░рдХреВрди рд╢реЛрдзрдд рдЕрд╕рддрд╛рдирд╛ рд╕рдЧрд│реНрдпрд╛рдВрдЪреЗ рдХрд╛рдо рдерд╛рдВрдмрддреЗ. рдореНрд╣рдгреВрди рд╢рд╛рд│рд╛ рд╢реЗрдЬрд╛рд░реА рдПрдХ рд╕рдВрдЧреНрд░рд╣рд╛рд▓рдп ЁЯПЫя╕П рдареЗрд╡рддреЗ, рдкреНрд░рдЪрдВрдб рдкреНрд░рд╢реНрдирд╛рдВрд╕рд╛рдареА рдмрд╛рдВрдзрд▓реЗрд▓реЗ, рджрд░ рд░рд╛рддреНрд░реА office рдЪреНрдпрд╛ рдиреЛрдВрджреАрдВрддреВрди рднрд░рд▓реЗрд▓реЗ. рд╣реЗрдЪ OLAP тАФ online analytical processing, рд╕рд╣рд╕рд╛ рдПрдХ data warehouse.

рджрд░ рд░рд╛рддреНрд░реА рд╕рдЧрд│реЗ copy рди рдХрд░рддрд╛ рд╕рдВрдЧреНрд░рд╣рд╛рд▓рдп рддрд╛рдЬреЗ рдареЗрд╡рдгреНрдпрд╛рд╕рд╛рдареА office рдПрдХ рдмрджрд▓рд╛рдВрдЪреА рдбрд╛рдпрд░реА рдареЗрд╡рддреЗ: рдкреНрд░рддреНрдпреЗрдХ рд╡реЗрд│реА рд╢реНрд░реЗрдгреА рдмрджрд▓рд▓реА рдХреА рдПрдХ рдУрд│ рд▓рд┐рд╣рд┐рд▓реА рдЬрд╛рддреЗ. рд╕рдВрдЧреНрд░рд╣рд╛рд▓рдп рддреА рдбрд╛рдпрд░реА рд╡рд╛рдЪрддреЗ. рд╣реЗрдЪ change data capture (CDC).

ЁЯЧ║я╕П рдЖрдХреГрддреА

flowchart LR
    oltp["ЁЯЧДя╕П live room (OLTP)<br/>many tiny reads/writes ┬╖ row store"]
    olap["ЁЯПЫя╕П warehouse (OLAP)<br/>few huge reads ┬╖ columnar"]
    oltp -->|"ЁЯМЩ nightly ETL"| olap
    oltp -. "CDC: every change (trigger / WAL)" .-> olap

ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрд╡реГрддреНрддреА + рдПрдХ lab: https://school-edh.pages.dev/database/lesson-diagrams.html#l18

тЭУ рдХрд╛рдп

ЁЯдФ рдХрд╛

рдЪрд╛рд▓реВ рдЦреЛрд▓реАрд╡рд░рдЪреЗ рдЬрдб reports рдмрд╛рдХреА рд╕рдЧрд│реНрдпрд╛рдВрдирд╛ рд╣рд│реВ рдХрд░рддрд╛рдд, рдЖрдгрд┐ dashboards рдирд╛ рд╕рддрдд refresh рд╡реНрд╣рд╛рдпрд▓рд╛ рдЖрд╡рдбрддреЗ. рддреНрдпрд╛рдВрдирд╛ рддреНрдпрд╛рдВрдЪреНрдпрд╛рд╕рд╛рдареАрдЪ рдмрд╛рдВрдзрд▓реЗрд▓реНрдпрд╛ store рдордзреНрдпреЗ рд╣рд▓рд╡рд▓реНрдпрд╛рдиреЗ office рдЬрд▓рдж рдЖрдгрд┐ reports рд╕реНрд╡рд╕реНрдд рд░рд╛рд╣рддрд╛рдд.

ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)

db/demo.py рдордзрд▓реЗ olap() report рджреЛрдиреНрд╣реА рдкреНрд░рдХрд╛рд░реЗ рдЪрд╛рд▓рд╡реВрди рд╡реЗрд│ рдореЛрдЬрддреЗ, рдЙрддреНрддрд░реЗ рдЬреБрд│рддрд╛рдд рдХрд╛ рддрдкрд╛рд╕рддреЗ, рдордЧ cdc_grades trigger рдмрдирд╡рддреЗ рдЖрдгрд┐ рд░реЛрд╣рдирдЪреА maths рдЪреА рд╢реНрд░реЗрдгреА рдмрджрд▓рддреЗ.

ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛

python3 db/demo.py olap
python3 - <<'EOF'
import sqlite3
c = sqlite3.connect("db/school.db")
c.execute("UPDATE grades SET grade = 'A+' WHERE student_id = 2 AND subject = 'science'")   # same value: A+ тЖТ A+
c.execute("UPDATE grades SET grade = 'B+' WHERE student_id = 1 AND subject = 'maths'"); c.commit()
print(c.execute("SELECT grade_id, old, new FROM grade_changes").fetchall())
EOF

тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ

report on the live 200,000-line table: ~29 ms ┬╖ on the nightly summary (12 rows): ~0.08 ms (рддреБрдордЪреЗ рдЖрдХрдбреЗ рд╡реЗрдЧрд│реЗ рдЕрд╕рддреАрд▓), same answer: True, рдЖрдгрд┐ рдмрджрд▓рд╛рдВрдЪреНрдпрд╛ рдбрд╛рдпрд░реАрдд (9, 'B', 'A'). Snippet рдордзреНрдпреЗ trigger рджреЛрдиреНрд╣реА updates рдиреЛрдВрджрд╡рддреЛ тАФ рддреЛ рдкреНрд░рддреНрдпреЗрдХ UPDATE OF grade рд╡рд░ рдЪрд╛рд▓рддреЛ, рддреАрдЪ value рдкреБрдиреНрд╣рд╛ рд▓рд┐рд╣рд┐рдгрд╛рд▒реНрдпрд╛ update рд╡рд░рд╣реА.

ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ

рдХреЛрдгрддреЗ рдкреНрд░рд╢реНрди office рдордзреНрдпреЗ рдЖрдгрд┐ рдХреЛрдгрддреЗ рд╕рдВрдЧреНрд░рд╣рд╛рд▓рдпрд╛рдд рд╣рд╡реЗрдд рд╣реЗ рддреБрдореНрд╣реА рд╕рд╛рдВрдЧреВ рд╢рдХрддрд╛, рдЖрдгрд┐ summary table рдЖрдгрд┐ рдмрджрд▓рд╛рдВрдЪреА рдбрд╛рдпрд░реА рд╡рд╛рдкрд░реВрди report рдЪрд╛рд▓реВ рдЦреЛрд▓реАрддреВрди рдмрд╛рд╣реЗрд░ рд╣рд▓рд╡реВ рд╢рдХрддрд╛.

тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛

ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рдмрд╣реБрддреЗрдХ companies product рд╕рд╛рдареА Postgres/MySQL рдЖрдгрд┐ analytics рд╕рд╛рдареА warehouse рдЪрд╛рд▓рд╡рддрд╛рдд, ETL рдХрд┐рдВрд╡рд╛ CDC pipelines рдиреЗ рдЬреЛрдбрд▓реЗрд▓реЗ тАФ data engineering рдЗрдереВрдирдЪ рд╕реБрд░реВ рд╣реЛрддреЗ.

ЁЯОУ рд░реЗрдХреЙрд░реНрдб рд░реВрдо рдЖрддрд╛ рдкреВрд░реНрдгрдкрдгреЗ рддреБрдордЪреА

рдЪрд┐рдХрдЯ рдЪрд┐рдареНрдареНрдпрд╛ тЖТ рдиреЛрдВрджрд╡рд╣реНрдпрд╛ рдЖрдгрд┐ keys тЖТ рдЕрднрд┐рд▓реЗрдЦрдкрд╛рд▓ тЖТ рдкреЗрдиреНрд╕рд┐рд▓рдордзрд▓реА рдиреЛрдВрджрд╡рд╣реА тЖТ рдПрдХ рддрдереНрдп, рдПрдХ рдЬрд╛рдЧрд╛ тЖТ рдХреЕрдЯрд▓реЙрдЧ тЖТ рджреЛрди рдХрд╛рд░рдХреВрди тЖТ рдиреВрддрдиреАрдХрд░рдг тЖТ рдЖрдЧреАрдкрд╛рд╕реВрди рд╕реБрд░рдХреНрд╖рд┐рдд рдкреНрд░рдд тЖТ рдЕрдзрд┐рдХ рдЦреЛрд▓реНрдпрд╛ тЖТ on call тЖТ рдХреБрд▓реВрдкрдмрдВрдж рдиреЛрдВрджрд╡рд╣реА тЖТ rankings тЖТ рдбрд╛рдпрд░реА тЖТ рдЦреЛрд▓реАрдЪреНрдпрд╛ рдкреНрд░рддреА тЖТ рдЦреЛрдХрд╛ рдШреЗрдКрди рдЬрд╛рдгрд╛рд░реА рдорджрддрдиреАрд╕ тЖТ рд╢реЗрдЬрд╛рд░рдЪреЗ рд╕рдВрдЧреНрд░рд╣рд╛рд▓рдп. ЁЯЧДя╕ПЁЯОУ

git checkout main
python3 db/demo.py     # every lesson, 01тАУ18, in one run

ЁЯПЫя╕П Lesson 18 тАФ OLTP vs OLAP: the office and the archive

ЁЯУН You are here: Lesson 18 of 18 тАФ the final lesson! ┬╖ Previous: lesson-17-app-code

Part 3 тАФ going deeper. Lessons 01тАУ12 built and ran the record room. Lessons 13тАУ18 are the topics interviews and incidents ask about тАФ each one runs for real on the same school.db.


ЁЯУж What's in this branch

The complete course, plus olap() in db/demo.py: a monthly attendance report run on the live 200,000-line table and on a summary table built by a "nightly ETL", and a trigger that records every grade change in grade_changes (change data capture).

ЁЯзТ Explain like I'm 5

The school office is busy all day with tiny jobs: mark Katrina present, fix Rohan's grade, enrol Diya. That is OLTP тАФ online transaction processing.

Once a year the head teacher asks a huge question: "attendance by month, for every year since the school opened". If you ask the office, everyone stops working while the clerks dig. So the school keeps an archive ЁЯПЫя╕П next door, built for huge questions, filled every night from the office's records. That is OLAP тАФ online analytical processing, usually a data warehouse.

To keep the archive fresh without copying everything every night, the office keeps a change diary: every time a grade changes, one line is written. The archive reads the diary. That is change data capture (CDC).

ЁЯЧ║я╕П Diagram

flowchart LR
    oltp["ЁЯЧДя╕П live room (OLTP)<br/>many tiny reads/writes ┬╖ row store"]
    olap["ЁЯПЫя╕П warehouse (OLAP)<br/>few huge reads ┬╖ columnar"]
    oltp -->|"ЁЯМЩ nightly ETL"| olap
    oltp -. "CDC: every change (trigger / WAL)" .-> olap

ЁЯЧ║я╕П Drawn version + a lab: https://school-edh.pages.dev/database/lesson-diagrams.html#l18

тЭУ What

ЁЯдФ Why

Heavy reports on the live room slow everyone else down, and dashboards love to refresh. Moving them to a store built for them keeps the office fast and the reports cheap.

ЁЯФз How (in this repo)

olap() in db/demo.py times the report both ways, checks the answers match, then creates the cdc_grades trigger and changes Rohan's maths grade.

ЁЯзк Try it

python3 db/demo.py olap
python3 - <<'EOF'
import sqlite3
c = sqlite3.connect("db/school.db")
c.execute("UPDATE grades SET grade = 'A+' WHERE student_id = 2 AND subject = 'science'")   # same value: A+ тЖТ A+
c.execute("UPDATE grades SET grade = 'B+' WHERE student_id = 1 AND subject = 'maths'"); c.commit()
print(c.execute("SELECT grade_id, old, new FROM grade_changes").fetchall())
EOF

тЬЕ Verify тАФ what you should see

report on the live 200,000-line table: ~29 ms ┬╖ on the nightly summary (12 rows): ~0.08 ms (your numbers differ), same answer: True, and (9, 'B', 'A') in the change diary. In the snippet, the trigger records both updates тАФ it fires on every UPDATE OF grade, even one that writes the same value.

ЁЯПБ What you just proved

You can say which questions belong in the office and which in the archive, and move a report off the live room with a summary table and a change diary.

тЪая╕П Common mistakes

ЁЯПн Why this matters in production: most companies run Postgres/MySQL for the product and a warehouse for analytics, joined by ETL or CDC pipelines тАФ data engineering starts here.

ЁЯОУ The record room is yours тАФ all of it

Sticky notes тЖТ registers and keys тЖТ the archivist тЖТ the pencil ledger тЖТ one fact, one place тЖТ the catalogue тЖТ two clerks тЖТ renovations тЖТ the fireproof copy тЖТ more rooms тЖТ on call тЖТ the locked register тЖТ rankings тЖТ the diary тЖТ copies of the room тЖТ the helper with a box тЖТ the archive next door. ЁЯЧДя╕ПЁЯОУ

git checkout main
python3 db/demo.py     # every lesson, 01тАУ18, in one run
тЖР Previousapp codeFinished! Take the quiz тЖТcheck what stuck

This page is the lesson's README from the lesson-18-oltp-olap branch, shown here so the whole School stays on one site. Code files open on GitHub at the same branch.