Перформанси на базата на податоци: Архитектура за предвидливо скалирање
Перформансите на базата на податоци ретко се уништуваат од една драматична грешка. Почесто, тие тивко се влошуваат: практично пребарување станува често користена патека, индекс што недостасува станува видлив при оптоварување, а задача во заднина почнува да се натпреварува со барањата од клиентите. До моментот кога графиците за латентност изгледаат алармантно, основниот проблем обично е архитектонски, а не единствен бавен израз.
Предвидливото скалирање значи дизајнирање систем чие однесување останува разбирливо додека растат сообраќајот, обемот на податоци и големината на тимот. Целта не е секое пребарување да биде што е можно побрзо. Целта е важната работа да биде сигурно брза, скапата работа намерно контролирана, а оперативните изненадувања полесни за дијагностицирање.
Почнете со оптоварувањето, а не со брендот на базата на податоци
Базата на податоци не е „бавна“ во апстрактна смисла. Таа е бавна во однос на оптоварувањето: стапки на барања, односи на читање/запишување, големини на записи, конкурентност, времетраење на трансакции и прифатливи времиња на одговор. Систем што ефикасно обработува пребарување во мал каталог може да се однесува многу поинаку при обработка на извештаи ограничени по закупец низ милиони редови.
Пред да воведете кешови, реплики или партиции, идентификувајте ги барањата што го дефинираат корисничкото искуство и деловниот ризик. За PHP апликација, тоа често значи крајните точки што се повикуваат при најавување, наплата, ажурирања на сметка, контролни табли и обработка во заднина.
- Кои пребарувања се извршуваат при секое барање?
- Кои табели постојано растат?
- Кои операции мора да бидат силно конзистентни?
- Кои екрани можат да толерираат малку задоцнети податоци?
- Кои задачи можат да се извршуваат асинхроно или во серии?
Овие прашања ја претвораат работата на перформансите од реактивно дотерување во експлицитна дизајнерска вежба. Тие исто така спречуваат чест начин на неуспех: оптимизирање на редок административен извештај додека примарниот тек за клиентите останува без соодветен индекс.
Направете ги патеките за пристап намерни
Индексите се меѓу најефективните алатки за перформанси на база на податоци, но не се бесплатни. Тие трошат складишен простор, додаваат работа при вметнувања и ажурирања и може да бидат игнорирани ако обликот на пребарувањето не им одговара. Индексот треба да постои затоа што поддржува познат образец на пристап.
Разгледајте табела со нарачки за повеќе закупци, каде крајна точка наменета за клиенти ги прикажува неодамнешните нарачки за една сметка:
SELECT id, status, total, created_at
FROM orders
WHERE account_id = ?
AND status = ?
ORDER BY created_at DESC
LIMIT 50;
Индекс усогласен со колоните за филтрирање и подредување може да ѝ помогне на базата на податоци да ги стесни кандидатските редови и да избегне непотребно сортирање:
CREATE INDEX orders_account_status_created_at_idx
ON orders (account_id, status, created_at DESC);
Точниот најдобар индекс зависи од машината на базата на податоци, распределбата на податоците и другите пребарувања кон табелата. Трајната поука е поширока: прегледајте го планот за извршување за вистинското пребарување, со репрезентативни параметри и реалистични податоци. Не претпоставувајте дека индексот се користи само затоа што постои.
Исто така, избегнувајте избирање податоци што апликацијата не ѝ се потребни. Преземањето голема текстуална колона или сериски товар за секој ред во крајна точка со листа ги зголемува I/O, употребата на меморија, мрежниот трошок и трошокот за хидратација во PHP. Тесно пребарување често е подобра оптимизација од покомплициран кеш.
Пагинацијата заслужува архитектонска одлука
Пагинацијата со поместување е лесна за имплементирање, но длабоките поместувања стануваат сè понеефикасни бидејќи базата на податоци можеби сепак треба да помине низ претходните редови. Исто така може да даде збунувачки резултати кога податоците се менуваат меѓу барањата.
За доводи, дневници на активности и ресурси подредени по време, пагинацијата заснована на курсор обично е постабилна. Користете детерминистичко подредување, обично временска ознака плус единствен разрешувач на изедначувања:
SELECT id, created_at, event_type
FROM audit_events
WHERE account_id = ?
AND (created_at, id) < (?, ?)
ORDER BY created_at DESC, id DESC
LIMIT 100;
На овој образец му е потребен индекс што ги поддржува филтерот по закупец и подредувањето. Тој исто така го прави API-договорот појасен: клиентите продолжуваат од позиција наместо да бараат произволен број на страница.
Одржувајте ги трансакциите мали и целисходни
Трансакцијата заштитува единица на исправност; таа не треба да стане контејнер за неповрзана работа на апликацијата. Држењето трансакција отворена додека PHP повикува надворешен API, рендерира документ, чека одговор од редица или извршува обемна пресметка го зголемува времето на заклучување и зафатеноста на конекциите.
Валидирајте ги влезовите и подгответе ги потребните податоци пред да влезете во трансакцијата. Во неа, направете ги потребните читања и запишувања, спроведете ги инваријантите, па веднаш потврдете ја трансакцијата. Ако надворешната работа мора да следи по успешно запишување, моделирајте ја како посебен чекор со сигурен механизам за предавање, наместо да претпоставувате дека двата системи можат да учествуваат во една трансакција.
Неуспесите при конкурентност се нормални во системи со писатели што се натпреваруваат. Кодот треба да разликува привремени неуспеси, како застои или конфликти при сериализација, од трајни неуспеси при валидација. Ограничен обид одново може да биде соодветен кога операцијата е безбедна за повторување. Тоа бара идемпотентност: повторните обиди не смеат да создаваат дупликат плаќања, е-пораки или записи.
Користете кеширање за намалување на работата, а не за прикривање неизвесност
Кеширањето е вредно кога основните податоци се скапи за пресметување или често се читаат, но воведува втора состојба за која треба да се размислува. Кеш без јасна стратегија за сопственост и инвалидирање може да направи системот да биде брз и неточен.
Добри кандидати за кеш се стабилни референтни податоци, рендерирани фрагменти и скапи агрегатни резултати со прифатлив прозорец на свежина. Лоши кандидати се вредности што мора веднаш да го одразуваат секое запишување, освен ако патеката за инвалидирање навистина е сигурна.
Практичен пристап е да се дефинира однесувањето на кешот како дел од функционалноста:
- Кој клуч ја идентификува вредноста, вклучително со закупецот и опсегот на авторизација?
- Колку долго вредноста смее да остане застарена?
- Кој настан ја инвалидира или освежува?
- Што се случува кога кешот не е достапен?
- Дали промашување на кешот може да предизвика многу конкурентни барања повторно да ја изградат истата вредност?
За многу крајни точки, точниот резервен механизам е примарната база на податоци со разумна заштита од оптоварување. Кешот треба постепено да ги влошува перформансите, а не да ја направи апликацијата недостапна или тивко да враќа податоци од погрешен контекст на клиентот.
Одделете ја онлајн работата од масовната работа
Интерактивните барања и сериската обработка имаат различни потреби за перформанси. Барање што опслужува корисник треба да го направи минимумот потребен за враќање точен одговор. Увозот на датотеки, повторното градење индекси за пребарување, генерирањето извештаи и испраќањето известувања припаѓаат во асинхрони работници каде пропусноста може да се контролира.
Ова раздвојување е важно на слојот на базата на податоци. Големо ажурирање или пребарување за извештај може да се натпреварува со сообраќајот од барања за CPU, заклучувања, баферска меморија и конекции. Сериските задачи треба да обработуваат ограничени делови, редовно да потврдуваат трансакции и да бидат доволно набљудливи за безбедно да се паузираат или продолжат.
На пример, работник може да преземе ограничен сет необработени записи, атомски да означи напредок и да продолжи во подоцнежни итерации. Избегнувајте вчитување цела табела во PHP меморија или обвиткување долготрајна серија во една трансакција. И базата на податоци и околината за распоредување полесно се опоравуваат од мали, повторливи единици работа.
Заштитете го базенот на конекции
Секој процес на апликацијата што може да отвори конекции со базата на податоци придонесува кон конкурентноста. Во контејнеризирани PHP распоредувања, скалирањето веб-работници без да се земат предвид ограничувањата на конекциите на базата на податоци може да ја исцрпи базата пред употребата на CPU да изгледа висока.
Поставете експлицитни ограничувања за работниците на апликацијата и конекциите со базата на податоци. Повторно користете конекции каде што моделот на извршување го поддржува тоа, но земете ги предвид застарените конекции и рестартите при распоредување. Следете ги активните конекции, сесиите што чекаат, бавните пребарувања, чекањата за заклучување, стапките на грешки и латентноста на барањата заедно. Гледањето само на една метрика поттикнува погрешни заклучоци.
Репликите за читање можат да помогнат при оптоварувања со многу читања, но воведуваат и доцнење на репликацијата и сложеност при рутирање. Не испраќајте читање што мора веднаш да забележи претходно запишување до реплика, освен ако моделот на конзистентност изречно го поддржува тоа однесување. Архитектурата делумно е дисциплина на правење такви компромиси видливи во кодот и очекувањата од API.
Мерете континуирано, менувајте внимателно
Промените на перформансите треба да почнат со докази: дневник на бавни пребарувања, податоци од следење, план за извршување или повторлив профил на оптоварување. Потоа променете една значајна променлива, потврдете го резултатот и внимавајте на регресии во трошокот за запишување, однесувањето на заклучувањата или употребата на меморија.
Промените на шемата заслужуваат иста грижа како изданијата на апликацијата. Додавањето индекс или менувањето голема табела може да влијае на продукцискиот сообраќај, зависно од машината и операцијата. Тестирајте ги миграциите со репрезентативни податоци, разберете го однесувањето на заклучувањата и имајте план за распоредување што ја зачувува достапноста.
Предвидливото скалирање не е целна линија до која се стигнува со херојско препишување. Тоа е збир на навики: моделирајте ги обрасците на пристап, одржувајте ги критичните патеки тесни, ограничете ја скапата работа и набљудувајте го системот пред да погодувате. Кога тие навики се вградени во апликацијата рано, растот станува инженерски проблем со познати лостови, наместо итна состојба што чека зад следното успешно лансирање.