PostgreSQL ішкі механизмдерінің ерекшеліктері оның кейбір жағдайларда өте жылдам, ал басқаларында «өте жылдам емес» болуына мүмкіндік береді. Бүгін біз ДҚБЖ қалай жұмыс істейтіні мен әзірлеуші онымен не істейтіні арасындағы қайшылықтың классикалық мысалына тоқталамыз - UPDATE және MVCC принциптері.
Шағын әңгімеден
Жол ЖАҢАЛЫҚТАУ пәрменімен өзгертілгенде, шын мәнінде екі әрекет орындалады: DELETE және INSERT. IN жолдың ағымдағы нұсқасы xmax UPDATE орындаған транзакция санына тең орнатылады. Содан кейін ол құрылады жаңа нұсқасы бірдей сызық; оның xmin мәні алдыңғы нұсқаның xmax мәніне сәйкес келеді.
Осы транзакция аяқталғаннан кейін біраз уақыттан кейін ескі немесе жаңа нұсқасына байланысты COMMIT/ROOLBACK
, танылатын болады «өлі» (өлі кортеждер) өтіп бара жатқанда VACUUM
кестеге сәйкес және тазартылады.
Бірақ бұл бірден болмайды, бірақ «өлілермен» проблемаларды өте тез алуға болады - қайталанатын немесе
№1: Мен оны жылжытқанды ұнатамын
Сіздің әдісіңіз іскерлік логикада жұмыс істейді делік және кенеттен ол қандай да бір жазбада X өрісін жаңарту қажет екенін түсінеді:
UPDATE tbl SET X = <newX> WHERE pk = $1;
Содан кейін, орындалу барысында, Y өрісі де жаңартылуы керек:
UPDATE tbl SET Y = <newY> WHERE pk = $1;
... сосын сонымен қатар Z - неге ұсақ-түйекке уақыт жұмсау керек?
UPDATE tbl SET Z = <newZ> WHERE pk = $1;
Қазір дерекқорда бұл жазбаның қанша нұсқасы бар? Иә, 4 дана! Олардың біреуі өзекті және 3-ін сізден кейін [авто]ВАКУУМ арқылы тазалау керек.
Бұлай істеме! Қолдану бір сұраудағы барлық өрістерді жаңарту — әрқашан дерлік әдіс логикасын келесідей өзгертуге болады:
UPDATE tbl SET X = <newX>, Y = <newY>, Z = <newZ> WHERE pk = $1;
№2: пайдалану IS DISTINCT FROM, Лука!
Сонымен, сіз әлі де қаладыңыз
UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2;
Шамамен осы пішіндегі сұрау бос жаңа өрісті толтыру үшін емес, деректердегі кейбір қателерді түзету үшін жиі және әрқашан дерлік болады. Сонымен қатар, оның өзі бар деректердің дұрыстығы мүлде ескерілмейді - бекер! Яғни, жазба дәл керек нәрсе болса да, қайта жазылады - бірақ неге? Оны түзетейік:
UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2 AND X IS DISTINCT FROM <newX>;
Көптеген адамдар мұндай керемет оператордың бар екенін білмейді, сондықтан мұнда алдау парағы бар IS DISTINCT FROM
және басқа логикалық операторлар көмектеседі:
... және кешендегі операциялар туралы аз ROW()
- өрнектер:
№3: Сүйіктімді... блоктау арқылы танимын
іске қосылып жатыр екі бірдей параллель процесс, олардың әрқайсысы жазбаны «орындалуда» деп белгілеуге тырысады:
UPDATE tbl SET processing = TRUE WHERE pk = $1;
Бұл процестер іс жүзінде бір-бірінен тәуелсіз әрекеттерді орындаса да, бірақ бір идентификатор ішінде екінші клиент бірінші транзакция аяқталғанша осы сұрау бойынша «құлыпталады».
№1 шешім: тапсырма алдыңғыға қысқарады
Оны қайтадан қосайық IS DISTINCT FROM
:
UPDATE tbl SET processing = TRUE WHERE pk = $1 AND processing IS DISTINCT FROM TRUE;
Бұл пішінде екінші сұрау дерекқорда ештеңені өзгертпейді, бәрі қазірдің өзінде болуы керек - сондықтан блоктау болмайды. Әрі қарай, біз қолданбалы алгоритмде жазбаның «табылмау» фактісін өңдейміз.
№2 шешім: кеңес беру құлыптары
Бөлек мақалаға арналған үлкен тақырып, ол туралы оқуға болады
№3 шешім: ақымақ қоңыраулар
Бірақ бұл дәл сізбен болуы керек бір жазбамен бір мезгілде жұмыс істеу? Немесе, мысалы, клиент жағында бизнес логикасын шақыруға арналған алгоритмдерді шатастырдыңыз ба? Ал ойласаңыз?..
Ақпарат көзі: www.habr.com