Oletame, et päringus tuleks otsida ridu mingi keeruka regulaaravaldise mustri järgi. Kumb oleks efektiivsem - kas kirjutada üks pikk ja keeruline muster või jagada muster alamosadeks ning kirjutada lausesse mitu AND-idega seotud alamtingimust?

Postitas Erki Eessaar, 19.10.2026 10:12:02 (muudeti 19.10.2026 10:39:11)
Tagasi nimekirja
Lõpuks sõltub kõik konkreetse süsteemi realisatsioonist. 

Argumendid selle poolt, et üks suur regulaaravaldis on parem.
  • Funktsioonikutsete lisakulu (Overhead)
Regulaaravaldise kontrollimine tähendab andmebaasimootori jaoks spetsiifilise funktsiooni (regex-mootori) väljakutsumist. Mitme tingimusega päringus tuleb potentsiaalselt iga rea puhul regex-mootor käivitada mitu korda. Ühe tingimusega päringus tehakse seda iga rea kohta ainult ühe korra. Isegi kui andmebaasisüsteem kasutab loogiliste operaatorite (AND) puhul n-ö lühistamist (short-circuit evaluation – kui esimene tingimus on väär, siis järgmisi ei kontrollita), peab sobivate või osaliselt sobivate kirjete puhul ikkagi tegema mitu kulukat funktsioonikutset.
  • Sõne mitmekordne läbimine
Kui kasutada mitut eraldi tingimust, peab andmebaas sama sõne mälus töötlema mitu korda. Ühe regulaaravaldise puhul analüüsib andmebaasisüsteemi optimeeritud regex-mootor sõne algusest lõpuni ühe pideva tegevusena, tehes olekuüleminekuid mälus palju tõhusamalt.

Argumendid, mis toetavad mitut tingimust.
  • Kontrollitavate mustrite töötlemine
Iga kontrolliga kaasneb oma töö, sealhulgas kontrollitava teksti teisendamine regex-mootori sisekujule. Kui kompileeritud mustreid hoitakse vahemälus, siis neid ei kompileerita tavaliselt iga rea jaoks uuesti. 
  • Kõiki tingimusi ei pea alati kontrollima
Mitme AND-tingimuse korral ei kontrollita tingimata kõiki tingimusi iga rea puhul: kui üks tingimus annab tulemuseks FALSE, võib ülejäänud kontrollid ära jätta. Optimeerija võib muuta ka tingimuste hindamise järjekorda. Seetõttu võivad mitu lihtsat kontrolli mõnikord konkureerida ühe keerukama kontrolliga.

Tegin katsetuse PostgreSQL (18) põhjal. Kasutatavas tabelis on üks miljon rida. Tingimusele vastab 99 464 rida. Kasutan EXPLAIN ANALYZE, et lause täita, vaadata täitmise plaani ja tegeliku täitmise aega. 

Päring 1:
EXPLAIN ANALYZE SELECT Count(*) AS cnt
FROM Health_care_visit
WHERE reason ~ '^[NM]'
AND reason !~ '^(.o)'
AND reason ~ '.{2}[ts]\.$';

Päring 2:
EXPLAIN ANALYZE SELECT Count(*) AS cnt
FROM Health_care_visit
WHERE reason~'^[NM][^o].*[ts]\.$';


Täitmise plaan oli üldiselt sama, kuid sõltuvalt päringu variandist oli andmebaasisüsteemi hinnang (cardinality estimate) kui mitu rida vastab tingimusele, veidi erinev. Käivitasin päringuid mitu korda. Tulemused stabiliseerusid:
  • Päring 1 umbes 350 ms
  • Päring 2 umbes 265 ms
(350-265)/350*100%=85/350*100% => ligikaudu 24,3%
 
Päring 2 on ~24% kiirem (säästab 85 ms käivituse kohta).

Kas postitus oli kasulik?

Anna postitusele hinnang (1 – halb, 5 – väga hea):

Keskmine hinne: Pole veel hinnatud