ویرگول
ورودثبت نام
Mahdi Aghaei
Mahdi Aghaei
Mahdi Aghaei
Mahdi Aghaei
خواندن ۲ دقیقه·۳ ماه پیش

یک قابلیت کمتر شناخته‌شده PostgreSQL برای مدیریت بازه‌ها

❌ اگر در PostgreSQL هنوز برای ذخیره بازه‌های زمانی از دو ستون start_at و end_at استفاده می‌کنید، شاید وقت آن رسیده با Range Types آشنا شوید.

جالب است بدانید این قابلیت از PostgreSQL 9.2 (سال ۲۰۱۲) وجود دارد، اما هنوز هم یکی از ویژگی‌های کمتر شناخته‌شده این دیتابیس محسوب می‌شود.

PostgreSQL برای انواع مختلف داده، Range Typeهای آماده‌ای دارد؛ مانند:

  • daterange

  • tsrange

  • tstzrange

  • int4range

  • int8range

  • numrange


خیلی از ما این مدل را استفاده می‌کنیم:

start_at TIMESTAMP, end_at TIMESTAMP

اما PostgreSQL نوع داده‌ای دارد که دقیقاً برای همین سناریو طراحی شده است:

period TSTZRANGE

شاید در نگاه اول فقط یک ستون کمتر به نظر برسد، اما مزایای آن بسیار فراتر از این است.


1️⃣ جستجوی Overlap بسیار ساده‌تر

با دو ستون معمولاً باید این شرط را بنویسید:

WHERE start_at < :new_end AND end_at > :new_start

اما با tstzrange:

WHERE period && tstzrange(:new_start, :new_end)

اپراتور && یعنی:

آیا این دو بازه با هم هم‌پوشانی دارند؟

هم خواناتر است و هم احتمال خطای منطقی کمتر می‌شود.


2️⃣ ایندکس بسیار قدرتمندتر برای داده‌های حجیم 🚀

اگر جدول شما میلیون‌ها رکورد داشته باشد (مثل رزروها، کمپین‌ها یا قیمت‌ها)، می‌توانید از GiST Index استفاده کنید:

CREATE INDEX idx_period ON reservations USING GIST(period);

از این به بعد کوئری‌هایی مثل:

WHERE period && tstzrange(...)

با استفاده از ایندکس اجرا می‌شوند و عملکرد بسیار بهتری نسبت به شرط‌های پیچیده روی دو ستون خواهند داشت.


3️⃣ جلوگیری از ثبت بازه‌های متداخل، بدون حتی یک خط کد

فرض کنید هیچ دو رزروی برای یک اتاق نباید روی هم بیفتند.

با دو ستون معمولاً باید این منطق را در لایه Application پیاده‌سازی کنید.

اما PostgreSQL خودش این کار را انجام می‌دهد:

ALTER TABLE reservations ADD CONSTRAINT no_overlap EXCLUDE USING gist ( room_id WITH =, period WITH && );

از این لحظه، اگر کسی بخواهد یک رزرو متداخل ثبت کند، خود دیتابیس جلوی آن را می‌گیرد.


4️⃣ اپراتورهای آماده

Range Types مجموعه‌ای از عملگرهای بسیار کاربردی دارد:

period @> now()

آیا این بازه، زمان فعلی را شامل می‌شود؟

period <@ other_period

آیا این بازه داخل بازه دیگری قرار دارد؟

lower(period) upper(period)

دریافت شروع و پایان بازه.


اگر با داده‌هایی مثل این سروکار دارید:

✅ رزرو
✅ شیفت کاری
✅ اعتبار قیمت
✅ کمپین‌های تخفیف
✅ بازه ارسال
✅ هر چیزی که مفهوم «از ... تا ...» دارد

به نظرم daterange، tsrange یا tstzrange ارزش بررسی جدی دارند.

گاهی قابلیت‌هایی که سال‌هاست در PostgreSQL وجود دارند، بیشترین تأثیر را روی کیفیت طراحی دیتابیس، خوانایی کوئری‌ها و عملکرد سیستم می‌گذارند.

شما از Range Types در پروژه‌هایتان استفاده کرده‌اید؟ تجربه‌تان چه بوده است؟

#PostgreSQL #Database #SQL #Backend #SoftwareEngineering #Performance

postgresqlperformancesoftware engineeringbackend
۳
۰
Mahdi Aghaei
Mahdi Aghaei
شاید از این پست‌ها خوشتان بیاید