Logo GH

PostgreSQL: საუკეთესო პრაქტიკა და ინდექსაცია

(განყოფილება: ტექნოლოგიები და ინფრასტრუქტურა)

მოკლე რეზიუმე

PostgreSQL არის „სიმართლის ბირთვი“ ფულისთვის, KYC და იურიდიულად მნიშვნელოვანი ჩანაწერები iGaming- ში. იგი იძლევა ACID გარანტიებს, მძლავრ SQL და გაფართოებას. ტურნირებისა და PSP-webhuks- ის მწვერვალების შესანარჩუნებლად, კრიტიკულია: კომპეტენტური სქემა, ინდექსები, წვეულება, ავტო-ვაკუუმი, WAL tuning და დაკვირვება. ქვემოთ მოცემულია პრაქტიკისა და შაბლონების დიზაინერი.

1) არქიტექტურა და SLO

PostgreSQL- ის როლი: ჩანაწერის ლიდერი + კითხვის შენიშვნები; ცხელი ეკრანებისთვის - ქეში/პროექციები (Redis/მატერიალიზებული წარმოდგენები).
SLO მაგალითები: p99 'INSERT/განახლება' საფულე 25-40 ms; p99 წონასწორობის კითხვა 10-15 ms; რეპლიკების ლაგი 2-5 წმ; ხელმისაწვდომობა 99. 9%.
Read-after-write პოლიტიკა: მომხმარებლის ეკრანები იკითხება ლიდერის მხრიდან გარიგების შემდეგ ან ელოდება რეპლიკაციის გზას.

2) სქემების დიზაინი

ფულის ბირთვის ნორმალიზაცია (საფულეები, ლედგერი) + კითხვის დენორმალიზაცია (CQRS/პროექციები).

მკაცრი შეზღუდვები: 'NOT NULL', 'CHECH', 'UNIQUE', FK მიზნობრივი 'ON DELETE/განახლება "(RESTRICT/SET NULLL LD D D LE E E E IED D D AD D D D D D DUIIIID D D D D D ID D D D EEED D D d

სქემის ვერსია: მიგრაცია up/down, feature დროშები; მოერიდეთ ცხელი დროის შეცვლას.
იდენტიფიკატორები: 'BIGINT' + თანმიმდევრობა (ან ULID/UUIDv7 განაწილებისთვის). ცხელი ჩანართებისთვის - თანმიმდევრობა ცალკეულ tablespace/WAL ტომში.

3) ინდექსაცია: რა, სად და როგორ

3. 1 B-Tree (ნაგულისხმევი)

როდის: ზუსტი შესაბამისობა, დიაპაზონი, დახარისხება, 'JOIN' FK- ზე.
ნიმუშები: 'WHERE player _ id =?', 'ORDER BY created _ at DESC LIMIT 100'.

პრაქტიკა:
  • მრავალფუნქციური ინდექსები - შეასრულეთ პირობები.
  • Covering: `INCLUDE (...)` для index-only scan.
  • ცალკეული ინდექსი 'ORDER BY... DESC '„ფირზე“.
sql
CREATE INDEX idx_tx_player_created_desc
ON tx (player_id, created_at DESC) INCLUDE (amount_cents, status);

3. 2 GIN (JSONB, მასივები, სისრულე)

როდის: JSONB ძებნა კლავიშებზე/ბილიკებზე, ჭდეების მასივები, FTS.
პარამეტრები: 'gin _ trgm _ ops' ტრიგრამებისთვის, 'jsonb _ path _ ops '/' jsonb _ ops'.
პრაქტიკა: მკაცრად შეზღუდეთ ძიების ველები და იფიქრეთ კარდინალობაზე.

sql
CREATE INDEX idx_profile_jsonb_gin
ON player_profile USING GIN (data jsonb_path_ops);

-- Search by email/name with typos
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE INDEX idx_player_trgm ON player USING GIN (email gin_trgm_ops);

3. 3 GiST (გეო/დიაპაზონი/ხელმოწერები)

როდის: გეოლოკაცია (IP-geo, რადიუსი), ინტერვალები, nearest-neighbor.
ნაკლებად გამოიყენება ფულის ბირთვში, სასარგებლოა გეო შეზღუდვების/პასუხისმგებლობის თამაშისთვის.

3. 4 BRIN (დროის დიდი „დანართი“)

როდის: მილიარდობით სტრიქონი, დროის ბუნებრივი კორელაცია (ფსონების/მოვლენების ჟურნალები).
დადებითი: მცირე ზომა, იაფი მომსახურება.
უარყოფითი მხარეები: უხეში სელექციურობა შეიძლება გაერთიანდეს პარტიზანასთან.

sql
CREATE INDEX idx_bets_brin ON bets USING BRIN (created_at) WITH (pages_per_range = 64);

3. 5 Hash

იშვიათად არის საჭირო: ერთი სვეტის თანასწორობა დიაპაზონის არარსებობის შემთხვევაში; უფრო ხშირად საკმარისია B-Tree.

3. 6 ნაწილობრივი და გამონათქვამები

პარტიული ინდექსი: აჩქარებს ცხელ ქუდს (აქტიური, 'status =' pending ").
Expression index: გასაღების წინასწარ განსაზღვრა ('lower (email)', '(data->' psp _ tx ')').

sql
CREATE INDEX idx_withdraw_pending ON withdrawals (player_id)
WHERE status = 'pending';

CREATE INDEX idx_tx_psp_tx ON tx ((data->>'psp_tx'));

3. 7 ინდექსების საწინააღმდეგო

„ინდექსი ყველაფრისთვის“: ინდექსების ჭარბი რაოდენობა ანელებს ჩანაწერს და VACUUM- ს.
დუბლირების ინდექსები (იგივე სვეტების ნაკრები/რიგი).
სვეტზე ინდექსი ძალიან დაბალი კარდინალობით (მაგალითად, 'status' 2 მნიშვნელობით) - გააკეთეთ ნაწილობრივი.

4) განაწილება

რატომ: შეამციროთ bloat, დააჩქაროთ VACUUM/სკანერები, შეამსუბუქეთ retention/არქივი.
სქემები: RANGE თარიღი (დღე/კვირა) განაკვეთების ლოგოსთვის; HASH 'player _ id' - ით დიდი მომხმარებლის ცხრილებისთვის; კომბინირებული.
როტაციის პრაქტიკა: წინასწარ შექმნათ მომავალი ნაწილები, 'ATTACH PARTITION', ძველი არქივი - 'DETACH' + მოძრაობა.

sql
CREATE TABLE bets (
bet_id BIGINT PRIMARY KEY,
player_id BIGINT NOT NULL,
created_at TIMESTAMPTZ NOT NULL,
amount_cents BIGINT NOT NULL
) PARTITION BY RANGE (created_at);

CREATE TABLE bets_2025_11_05 PARTITION OF bets
FOR VALUES FROM ('2025-11-05') TO ('2025-11-06');

5) ჩანართები/განახლებები მინიმალური ფრაგმენტაციით

HOT განახლებები: შეინახეთ 'fillfactor' (მაგალითად, 90) ცხრილში გვერდზე უფასო ადგილისთვის.
TOAST: დიდი JSONB/ტექსტები - დააკვირდით კომპაქტაციას; შეინახეთ მძიმე ველები ცალკე ცხრილში.
UPSERT: გამოიყენეთ 'ON CONFLICT... DO განახლება 'იდემპოტენტური ლოგიკით.

sql
INSERT INTO wallet (player_id, balance_cents, updated_at)
VALUES ($1, $2, now())
ON CONFLICT (player_id) DO UPDATE
SET balance_cents = wallet. balance_cents + EXCLUDED. balance_cents,
updated_at = now();

6) გარიგებები, დაბლოკვა და კონკურენცია

იზოლაციის დონე: 'READ COMMITTED' ტრასების უმეტესობისთვის; 'REPEATABLE '/' SERIALIZABLE' წერტილოვანი (მოხსენებები, ოფლაინ-ბრძოლები). ნუ შეინარჩუნებთ მათ დიდხანს.
დაბლოკვის ტიპები: row-level (პესიმიზმი 'FOR განახლება'), table-level (DDL), advisory locks განაწილებული mutex- ისთვის.
Deadlocks: მოკლე გარიგებები, ერთეულების განახლების ერთიანი პროცედურა, Timeout ('lock _ timeout', 'statement _ timeout').
დავალებების რიგები: 'SKIP LOCKED' განაწილებული ქურდის აუზისთვის.

sql
-- batch processor removes work without racing
SELECT id FROM jobs
WHERE status='pending'
FOR UPDATE SKIP LOCKED
LIMIT 100;

7) Avtovakum, სტატისტიკა და bloat

VACUUM/ANALYZE: შეინარჩუნეთ შესაბამისი სტატისტიკა ('default _ statistics _ target'), tune AV ცხრილებზე (ქვემოთ მოყვანილი ბარიერი).
დააკვირდით wraparound (age (txid) <2 მილიარდი), 'vacuuum _ freeze _ min _ age ".
bloat კონტროლი: რეგულარული reindex/CLUSTER მძიმე ინდექსებზე მწვერვალების მიღმა; წვეულება ამცირებს პრობლემის მასშტაბს.

პოლიტიკის მაგალითი (ცხრილის პარამეტრები):
sql
ALTER TABLE tx SET (
autovacuum_vacuum_scale_factor = 0. 05,
autovacuum_analyze_scale_factor = 0. 02,
autovacuum_vacuum_cost_limit = 4000
);

8) მეხსიერება, ჩეკები და WAL

მეხსიერება

'shared _ buffers': 20-25% RAM (დამოკიდებულია პროფილზე).
'work _ mem': ოპერაციისთვის! ჩამოაყალიბეთ კონსერვატიული (მაგალითად, 8-64MB) და გაზარდეთ წერტილოვანი საანგარიშო როლებისთვის.
'maintenance _ work _ mem': დიდი ინდექსები/აღდგენა (512MB-2GB დავალებით).

WAL და checkpoints

NVMe WAL- ისთვის, ცალკეული ტომი; 'wal _ compression = on'.
'checkpoint _ timeout' 10-15 წთ, 'max _ wal _ size' ცვლილებების მოცულობით, 'checkpoint _ completion _ target _ 0. 9`.
ჩანართების მწვერვალებისთვის - ბატჩის ჩანართები და ჯგუფური კომუნები.

9) რეპლიკაცია და წინააღმდეგობა

ლიდერის შენიშვნები: სინქრონიზებული უახლოესი (semi-sync) RPO-0-30s- ისთვის; ასინქრონული კითხვისთვის/ანალიტიკოსებისთვის.
პრომოუშენი და fencing: Patroni/რეპლიკა მენეჯერი; გამორიცხეთ „ორმაგი ლიდერი“.
Hot standby: 'hot _ standby _ feedback' ფრთხილად (bloat ზრდა), უკეთესი - მოიპარეთ გრძელი გარიგებები რეპლიკებზე.

10) Bacaps და PITR

სრული + სავარაუდო ზურგჩანთა, ოფსეტური ასლები; 'archive _ command' WAL- ისთვის.
PITR: შეამოწმეთ აღდგენა დროულად სტენდებზე; რეგულირება RPO/RTO (საფულეები - წუთი, ლოგოები - ათობით წუთი).
DR (თამაშის დღე) სავარჯიშოები: რეგულარული აღდგენის შემოწმება.

11) JSONB და „მოქნილი სქემის“ მოდელი

JSONB შესანიშნავია იშვიათად წაკითხული/ცვალებადი ატრიბუტებისთვის (KYC მეტამონაცემები, PSP პარამეტრები).
მკაცრად დალაგეთ სავალდებულო ველები რელიეფის სვეტებში; JSONB - ნიუანსების „კუდისთვის“.
ინდექსაცია: GIN წერტილოვანი გამოყენებული მარშრუტებისთვის; მოერიდეთ „ერთ გიგანტურ GIN ყველაფერს“.

sql
-- partial GIN index only for documents with the desired key
CREATE INDEX idx_kyc_docnum ON kyc USING GIN ((data->'doc'->'number'))
WHERE data? 'doc';

12) სრული ტექსტი და fuzzy ძებნა

ჩაშენებული FTS: 'tsvector' + GIN; ტიპებისთვის - 'pg _ trgm'.
ლოგოების/თამაშების მძიმე მოსაძებნად - გადაყვანა საძიებო სისტემაში (ES/OpenSearch), ხოლო PG- ში შეინახეთ ბმული/მეტამონაცემები.

13) დაკვირვება და პროფილირება

pg _ statements: ტოპ ნელი/ხშირი მოთხოვნა, ნორმალიზაცია.
EXPAIN (ANALYZE, BUFFERS): წაიკითხეთ გეგმები, მოძებნეთ seq scan ცხელ გზაზე.
მეტრიკა: TPS, p95/p99, checkpoints, 'replication _ lag', deadlocks, bloat, AV ციკლები, cache-hit - 95%.
ალერტები: ლაგების ზრდა, „indle in transaction“, მოულოდნელი seq scan, WAL ქარიშხალი.

14) ნაერთების აუზი და მომზადებული მოთხოვნები

პულერი (PgBouncer) 'ტრანსფორმაციის' რეჟიმში ვებ ტრაფიკისთვის; 'სესია "- გრძელი კურსებისთვის/სარეზერვო ოფისისთვის.
Prepared statements/პარამეტრიზაცია ნაკლები პარსინგია, სტაბილური გეგმები.
შეზღუდეთ ბეკენდების მაქსიმალური რაოდენობა ('max _ connections' დაბალია; აუზი იღებს სარქველს).

15) უსაფრთხოება და შესაბამისობა

TLS ტრანზიტში, დისკის დაშიფვრა, KMS/გარე გასაღებები.
RBAC: მინიმალური უფლებები, როლების გამიჯვნა კითხვა/ჩაწერა/admin.
RLS (Row-Level Security) მულტფილმის სცენარებისთვის.
PII: შენიღბვა/ფსევდონიმი, შენახვის ვადა.
აუდიტი: "pgaudit '/აუდიტის გამომწვევი კრიტიკულ ცხრილებზე (საფულე/ლედგერი).

16) ტიპიური შაბლონები iGaming- ისთვის

16. 1 საფულე და ლედგერი (მკაცრი კოორდინაცია)

Индексы: `wallet(player_id PK)`, `ledger(player_id, ts DESC)` + `INCLUDE (delta_cents, reason)`.
გარიგება განაახლებს ბალანსს და წერს ledger- ში; semi-sync- ის რეპლიკაცია; ქეში მხოლოდ პროექციის მსგავსად.

16. 2 განაკვეთების ისტორია (მაღალი TPS, მოთამაშის კითხვა/დრო)

განაწილება დღის/კვირის მიხედვით, BRIN დროის მიხედვით + B-Tree '(player _ id, created _ at DESC) ".
Retenshn 'DETACH PARTITION' - ის საშუალებით არის არქივი OLAP- ში.

16. 3 Webhuks PSP (bursts, retrai)

"ნედლეული" მოვლენების ხაზი (append-only), დროის წვეულება, ნაწილობრივი ინდექსი 'status =' pending ".
Idempotence 'idempotence _ key '/' psp _ tx "(UNIQUE).

17) განხორციელების შემოწმების სია

1. დააფიქსირეთ SLO და read-after-write პოლიტიკა.
2. შეიმუშავეთ ძირითადი ინდექსები რეალური მოთხოვნებისთვის (მოთხოვნის პროფილი).
3. ჩართეთ განაწილება, სადაც არის retenshn/append ნიმუშები.
4. AV/ANALYZE პარამეტრი ცხრილში, დააკვირდით bloat/wraparound.
5. გახსენით მეხსიერება, WAL და ქვები მწვერვალის ფანჯრების ქვეშ.
6. განათავსეთ ნაერთების აუზი და 'pg _ stat _ statements'; აიღეთ ალერტები.
7. რეპლიკაცია + DR + PITR - სავალდებულოა; ჩაატარეთ სწავლებები.
8. შეზღუდეთ JSONB და GIN მხოლოდ საჭირო გზებით; გამოიყენეთ partial indexes.
9. მინიმუმამდე დაიყვანეთ გარიგების ხანგრძლივობა, გამოიყენეთ 'SKIP LOCKED "საათის რიგებისთვის.
10. აუდიტი/PII/დაშიფვრა/როლური მოდელი - გადახდის დაწყებამდე.

18) ანტიპატერები

ერთი „უნივერსალური“ ინდექსი ყველაფრისთვის და მოთხოვნების ანალიზის არარსებობა.
გრძელი „ჩამოკიდებული“ გარიგებები ('idle in transaction') ბლოკირება/ზრდა bloat.
დაეყრდნო რეპლიკებს read-after-write- ისთვის, ლაგის გამოკლებით.
შეინახეთ ყველაფერი JSONB- ში „მხოლოდ შემთხვევაში“ და მთელი დოკუმენტის ინდექსირება ერთი GIN.
VACUUM/ANALYZE ნულოვანი კონტროლი და ლაგების/ჩეკების მონიტორინგის არარსებობა.
მასობრივი მიგრაცია/DDL პიკის საათებში.

19) სასარგებლო snippets

მოთხოვნის გეგმა და ბუფერები

sql
EXPLAIN (ANALYZE, BUFFERS, VERBOSE)
SELECT amount_cents
FROM ledger
WHERE player_id = $1
ORDER BY ts DESC
LIMIT 100;

პროფილის „მძიმე“ მოთხოვნა

sql
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
SELECT query, calls, total_exec_time, mean_exec_time
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 20;

პარტიების როტაცია (იდეა)

sql
-- create a party for tomorrow
CREATE TABLE bets_2025_11_06 PARTITION OF bets
FOR VALUES FROM ('2025-11-06') TO ('2025-11-07');

შედეგები

PostgreSQL- ს შეუძლია „ფული და სიმართლე“ გადაიტანოს iGaming პლატფორმაზე, დატვირთვის ხაზოვანი ზრდით - თუ ინდექსები, წვეულებები, მანქანის აკუმულაცია, WAL/მეხსიერება, რეპლიკა/DR და დაკვირვება არის მოწესრიგებული. დაიწყეთ მოთხოვნის პროფილით და SLO, ააშენეთ ინდექსები რეალური ნიმუშებისთვის, განათავსეთ ცხელი ცხრილები, ჩართეთ მკაცრი ოპერაციული ჰიგიენა - და ბაზა პროგნოზირებს ტურნირებს და პიკის გადახდებს.

Contact

დაგვიკავშირდით

დაგვიკავშირდით ნებისმიერი კითხვის ან მხარდაჭერისთვის.ჩვენ ყოველთვის მზად ვართ დაგეხმაროთ!

Telegram
@Gamble_GC
ინტეგრაციის დაწყება

Email — სავალდებულოა. Telegram ან WhatsApp — სურვილისამებრ.

თქვენი სახელი არასავალდებულო
Email არასავალდებულო
თემა არასავალდებულო
შეტყობინება არასავალდებულო
Telegram არასავალდებულო
@
თუ მიუთითებთ Telegram-ს — ვუპასუხებთ იქაც, დამატებით Email-ზე.
WhatsApp არასავალდებულო
ფორმატი: ქვეყნის კოდი და ნომერი (მაგალითად, +995XXXXXXXXX).

ღილაკზე დაჭერით თქვენ ეთანხმებით თქვენი მონაცემების დამუშავებას.