| PGBENCH(1) | PostgreSQL 18.6 Documentation | PGBENCH(1) |
نام (NAME)
pgbench - اجرای آزمون محک (benchmark) روی PostgreSQL
خلاصه دستور (SYNOPSIS)
pgbench -i [option...] [dbname]
pgbench [option...] [dbname]
توضیحات (DESCRIPTION)
ابزار pgbench یک برنامه ساده برای اجرای آزمونهای محک (benchmark) روی PostgreSQL است. این برنامه توالی یکسانی از دستورهای SQL را به دفعات مکرر، احتمالاً در چندین نشست همزمان پایگاهداده اجرا کرده و سپس نرخ میانگین تراکنشها (تراکنش در ثانیه یا TPS) را محاسبه میکند. بهطور پیشفرض، pgbench سناریویی را آزمایش میکند که تقریباً بر پایه TPC-B است و شامل پنج دستور SELECT، UPDATE و INSERT در هر تراکنش میباشد. با این حال، سنجش سایر سناریوها با نوشتن فایلهای اسکریپت تراکنش سفارشی آسان است.
خروجی معمول از pgbench به این صورت است:
transaction type: <builtin: TPC-B (sort of)> scaling factor: 10 query mode: simple number of clients: 10 number of threads: 1 maximum number of tries: 1 number of transactions per client: 1000 number of transactions actually processed: 10000/10000 number of failed transactions: 0 (0.000%) latency average = 11.013 ms latency stddev = 7.351 ms initial connection time = 45.758 ms tps = 896.967014 (without initial connection time)
هفت خط اول برخی از مهمترین تنظیمات پارامتر را گزارش میدهند. خط ششم حداکثر تعداد تلاشها برای تراکنشهای دارای خطای سریالسازی یا بنبست را گزارش میکند (برای اطلاعات بیشتر به بخش Failures and Serialization/Deadlock Retries مراجعه کنید). خط هشتم تعداد تراکنشهای تکمیلشده و مورد نظر را گزارش میدهد (مورد دوم صرفاً حاصلضرب تعداد کلاینتها در تعداد تراکنشها به ازای هر کلاینت است)؛ این دو مقدار برابر خواهند بود مگر اینکه اجرا پیش از تکمیل با شکست مواجه شود یا اجرای برخی از دستورهای SQL ناموفق باشد. (در حالت -T تنها تعداد واقعی تراکنشها چاپ میشود.) خط بعدی تعداد تراکنشهای ناموفق ناشی از خطاهای سریالسازی یا بنبست را گزارش میکند (برای اطلاعات بیشتر به بخش Failures and Serialization/Deadlock Retries مراجعه کنید). خط آخر تعداد تراکنشها در هر ثانیه را گزارش میدهد.
آزمون تراکنش پیشفرض شبیه TPC-B نیازمند آن است که جدولهای مشخصی از قبل آماده شوند. pgbench باید با گزینه -i (مقداردهی اولیه) فراخوانی شود تا این جدولها ایجاد و مقداردهی شوند. (هنگامی که یک اسکریپت سفارشی را آزمایش میکنید، به این مرحله نیازی ندارید، اما در عوض باید هرگونه آمادهسازی لازم برای آزمون خود را انجام دهید.) مقداردهی اولیه به این صورت است:
pgbench -i [ other-options ] dbname
که در آن dbname نام پایگاهداده از قبل ایجادشده برای آزمایش است. (همچنین ممکن است برای تعیین نحوه اتصال به سرور پایگاهداده، به گزینههای -h، -p یا -U نیاز داشته باشید.)
Caution
دستور pgbench -i چهار جدول pgbench_accounts، pgbench_branches، pgbench_history و pgbench_tellers را ایجاد میکند و هرگونه جدول موجود با این نامها را از بین میبرد. اگر جدولهایی با این نامها دارید، بسیار مراقب باشید که از پایگاهداده دیگری استفاده کنید!
در مقدار پیشفرض “ضریب مقیاس (scale factor)” برابر با ۱، جدولها در ابتدا حاوی این تعداد ردیف هستند:
table # of rows --------------------------------- pgbench_branches 1 pgbench_tellers 10 pgbench_accounts 100000 pgbench_history 0
میتوانید (و برای بیشتر اهداف، احتمالاً باید) با استفاده از گزینه -s (ضریب مقیاس) تعداد ردیفها را افزایش دهید. همچنین در این مرحله میتوان از گزینه -F (ضریب پرشدگی یا fillfactor) استفاده کرد.
پس از انجام آمادهسازیهای لازم، میتوانید آزمون محک خود را با دستوری که شامل -i نیست اجرا کنید، یعنی:
pgbench [ options ] dbname
تقریباً در تمامی موارد، برای انجام یک آزمایش کاربردی به گزینههایی نیاز خواهید داشت. مهمترین گزینهها عبارتند از -c (تعداد کلاینتها)، -t (تعداد تراکنشها)، -T (محدودیت زمانی) و -f (مشخص کردن یک فایل اسکریپت سفارشی). برای فهرست کامل به ادامه متن مراجعه کنید.
گزینهها (OPTIONS)
موارد زیر به سه زیربخش تقسیم میشوند. گزینههای متفاوتی در زمان مقداردهی اولیه پایگاهداده و اجرای بنچمارکها استفاده میشوند، اما برخی گزینهها در هر دو حالت کاربرد دارند.
گزینههای مقداردهی اولیه (Initialization Options)
pgbench آرگومانهای خط فرمان مقداردهی اولیه زیر را میپذیرد:
[-d] dbname
[--dbname=]dbname
-i
--initialize
-I init_steps
--init-steps=init_steps
d (Drop)
t (create Tables)
g یا G (Generate data, client-side or server-side)
با g (تولید داده در سمت کلاینت)، دادهها در کلاینت pgbench تولید شده و سپس به سرور ارسال میشوند. این روش پهنای باند کلاینت/سرور را به طور گسترده از طریق یک COPY به کار میگیرد. pgbench از گزینه FREEZE برای بارگذاری دادهها در جدولهای معمولی (غیرپارتیشنبندیشده) در نسخه ۱۴ یا جدیدترِ PostgreSQL استفاده میکند تا سرعت VACUUM بعدی را افزایش دهد. استفاده از g باعث میشود که هنگام تولید داده برای همه جدولها، گزارشگیری به ازای هر ۱۰۰٬۰۰۰ سطر یک پیام چاپ کند.
با G (تولید داده در سمت سرور)، تنها پرسوجوهای کوچک از کلاینت pgbench ارسال میشوند و سپس دادهها در سرور تولید میگردند. برای این حالت به پهنای باند قابلتوجهی نیاز نیست، اما سرور کار بیشتری انجام خواهد داد. استفاده از G باعث میشود که هنگام تولید داده هیچ پیام پیشرفتی در گزارشگیری چاپ نشود.
رفتار پیشفرض مقداردهی اولیه از تولید داده در سمت کلاینت استفاده میکند (معادل با g).
v (Vacuum)
p (create Primary keys)
f (create Foreign keys)
-F fillfactor
--fillfactor=fillfactor
-n
--no-vacuum
-q
--quiet
اگر G در -I مشخص شده باشد، این تنظیم هیچ اثری ندارد.
-s scale_factor
--scale=scale_factor
--foreign-keys
--index-tablespace=index_tablespace
--partition-method=NAME
--partitions=NUM
--tablespace=tablespace
--unlogged-tables
گزینههای بنچمارک (Benchmarking Options)
pgbench آرگومانهای خط فرمانی زیر را برای بنچمارک میپذیرد:
-b scriptname[@weight]
--builtin=scriptname[@weight]
به صورت اختیاری، یک وزن عدد صحیح پس از @ بنویسید تا احتمال انتخاب این اسکریپت در مقایسه با سایر اسکریپتها تنظیم شود. وزن پیشفرض 1 است. برای جزئیات بیشتر به بخشهای زیر مراجعه کنید.
-c clients
--client=clients
-C
--connect
-D varname=value
--define=varname=value
-f filename[@weight]
--file=filename[@weight]
به صورت اختیاری، یک وزن عدد صحیح پس از @ بنویسید تا احتمال انتخاب این اسکریپت در مقایسه با سایر اسکریپتها تنظیم شود. وزن پیشفرض 1 است. (برای استفاده از نام فایل اسکریپتی که شامل کاراکتر @ است، یک وزن به آن اضافه کنید تا ابهامی وجود نداشته باشد، به عنوان مثال filen@me@1.) برای جزئیات بیشتر به بخشهای زیر مراجعه کنید.
-j threads
--jobs=threads
-l
--log
-L limit
--latency-limit=limit
هنگامی که محدودسازی نرخ تراکنش (--rate=...) استفاده میشود، تراکنشهایی که بیش از limit میلیثانیه از زمانبندی عقب بیفتند و بنابراین امیدی به رسیدن به سقف تاخیر ندارند، اصلاً به سرور ارسال نمیشوند. آنها به طور جداگانه به عنوان skipped شمارش و گزارش میشوند.
هنگامی که گزینه --max-tries استفاده میشود، تراکنشی که به دلیل ناهنجاری سریالسازی (serialization anomaly) یا بنبست (deadlock) با شکست مواجه شود، در صورتی که زمان کل تمام تلاشهای آن بیشتر از limit میلیثانیه باشد، دوباره تلاش نخواهد شد. برای محدود کردن تنها زمان تلاشها و نه تعداد آنها، از --max-tries=0 استفاده کنید. به طور پیشفرض، گزینه --max-tries بر روی 1 تنظیم شده است و تراکنشهای دارای خطاهای سریالسازی/بنبست دوباره تلاش نمیشوند. برای اطلاعات بیشتر درباره تلاش مجدد چنین تراکنشهایی، به بخش Failures and Serialization/Deadlock Retries مراجعه کنید.
-M querymode
--protocol=querymode
در حالت prepared، ابزار pgbench نتیجه تحلیل پارس را از دومین تکرار پرسوجو مجدداً استفاده میکند، بنابراین pgbench سریعتر از سایر حالتها اجرا میشود.
حالت پیشفرض، پروتکل پرسوجوی ساده است. (برای اطلاعات بیشتر به فصل 54 مراجعه کنید.)
-n
--no-vacuum
-N
--skip-some-updates
-P sec
--progress=sec
-r
--report-per-command
-R rate
--rate=rate
هدفگذاری نرخ از طریق آغاز تراکنشها در امتداد یک خط زمانی زمانبندی با توزیع پواسون (Poisson-distributed) انجام میشود. زمانبندی زمان شروع مورد انتظار، بر اساس زمان اولین شروع کلاینت به جلو حرکت میکند، نه بر اساس زمان پایان تراکنش قبلی. این رویکرد به این معنی است که وقتی تراکنشها از زمان پایان برنامهریزیشده اولیه خود فراتر میروند، این امکان وجود دارد که تراکنشهای بعدی دوباره عقبافتادگی را جبران کنند.
هنگامی که محدودسازی نرخ (throttling) فعال است، تاخیر تراکنش گزارششده در پایان اجرا از زمانهای شروع زمانبندیشده محاسبه میشود؛ بنابراین شامل زمانی است که هر تراکنش باید منتظر میماند تا تراکنش قبلی به پایان برسد. به این زمان انتظار، زمان تاخیر زمانبندی (schedule lag time) گفته میشود و میانگین و حداکثر آن نیز به طور جداگانه گزارش میشود. تاخیر تراکنش نسبت به زمان شروع واقعی تراکنش، یعنی زمان صرفشده برای اجرای تراکنش در پایگاه داده، میتواند با کم کردن زمان تاخیر زمانبندی از تاخیر گزارششده محاسبه شود.
اگر --latency-limit همراه با --rate استفاده شود، ممکن است یک تراکنش به قدری عقب بیفتد که در زمان پایان تراکنش قبلی، از حد مجاز تاخیر فراتر رفته باشد، زیرا تاخیر از زمان شروع زمانبندیشده محاسبه میشود. چنین تراکنشهایی به سرور ارسال نمیشوند، بلکه به طور کامل نادیده گرفته شده و جداگانه شمرده میشوند.
بالا بودن زمان تاخیر زمانبندی نشاندهنده آن است که سیستم با تعداد کلاینتها و ریسمانهای انتخابشده، قادر به پردازش تراکنشها با نرخ تعیینشده نیست. هنگامی که میانگین زمان اجرای تراکنش طولانیتر از فاصله زمانی برنامهریزیشده میان هر تراکنش باشد، هر تراکنش متوالی بیشتر عقب خواهد افتاد و با طولانیتر شدن اجرای آزمون، زمان تاخیر زمانبندی مدام افزایش مییابد. در چنین شرایطی، باید نرخ تراکنش مشخصشده را کاهش دهید.
-s scale_factor
--scale=scale_factor
-S
--select-only
-t transactions
--transactions=transactions
-T seconds
--time=seconds
-v
--vacuum-all
--aggregate-interval=seconds
--exit-on-abort
توجه داشته باشید که شکستهای سریالسازی یا بنبست باعث متوقف شدن کلاینت نمیشوند، بنابراین تحت تأثیر این گزینه قرار نمیگیرند. برای اطلاعات بیشتر، بخش Failures and Serialization/Deadlock Retries را ببینید.
--failures-detailed
برای اطلاعات بیشتر، بخش Failures and Serialization/Deadlock Retries را ببینید.
--log-prefix=prefix
--max-tries=number_of_tries
--progress-timestamp
--random-seed=seed
تنظیم صریح دانه امکان بازتولید دقیق اجرای pgbench را تا جایی که به اعداد تصادفی مربوط میشود، فراهم میکند. از آنجا که وضعیت تصادفی به ازای هر ریسمان مدیریت میشود، در صورتی که به ازای هر ریسمان یک کلاینت وجود داشته باشد و وابستگی خارجی یا دادهای وجود نداشته باشد، این به معنای اجرای دقیقاً یکسان pgbench برای یک فراخوانی مشابه خواهد بود. از دیدگاه آماری، بازتولید دقیق اجراها ایده مناسبی نیست زیرا میتواند تغییرپذیری کارایی را پنهان کرده یا عملکرد را به طور غیرواقعی بهبود بخشد؛ مثلاً با دسترسی به همان صفحاتی که در اجرای قبلی استفاده شده بودند. با این حال، میتواند برای اشکالزدایی، مثلاً اجرای مجدد یک مورد خاص و پیچیده که منجر به خطا شده است، کمک بسیار بزرگی باشد. خردمندانه استفاده کنید.
--sampling-rate=rate
به یاد داشته باشید که هنگام پردازش فایل لاگ، نرخ نمونهبرداری را در نظر بگیرید. برای مثال، هنگام محاسبه مقادیر TPS، باید اعداد را متناسب با آن ضرب کنید (مثلاً با نرخ نمونهبرداری 0.01، تنها به میزان ۱/۱۰۰ از مقدار واقعی TPS را دریافت خواهید کرد).
--show-script=scriptname
--verbose-errors
گزینههای عمومی (Common Options)
دستور pgbench همچنین آرگومانهای معمول خط فرمان زیر را برای پارامترهای اتصال و سایر تنظیمات عمومی میپذیرد:
--debug
-h hostname
--host=hostname
-p port
--port=port
-U login
--username=login
-V
--version
-?
--help
وضعیت خروج (EXIT STATUS)
اجرای موفقیتآمیز با وضعیت 0 خارج میشود. کد خروج 1 نشاندهنده مشکلات ایستا مانند گزینههای نامعتبر خط فرمان یا خطاهای داخلی است که انتظار میرود هرگز رخ ندهند. خطاهای اولیه که هنگام شروع بنچمارک رخ میدهند (مانند شکست در اتصال اولیه) نیز با وضعیت 1 خارج میشوند. خطاهای حین اجرا مانند خطاهای پایگاه داده یا مشکلات موجود در اسکریپت منجر به کد وضعیت خروج 2 خواهند شد. در حالت اخیر، چنانچه گزینه --exit-on-abort مشخص نشده باشد، pgbench نتایج جزئی را چاپ خواهد کرد.
محیط (ENVIRONMENT)
PGDATABASE
PGHOST
PGPORT
PGUSER
این ابزار، مانند بیشتر ابزارهای دیگر PostgreSQL، از متغیرهای محیطی پشتیبانیشده توسط libpq استفاده میکند (به بخش 32.15 مراجعه کنید).
متغیر محیطی PG_COLOR مشخص میکند که آیا در پیامهای تشخیصی از رنگ استفاده شود یا خیر. مقادیر ممکن عبارتند از always، auto و never.
نکات (NOTES)
«تراکنش» اجرا شده در pgbench دقیقاً چیست؟ (What Is the “Transaction” Actually Performed in pgbench?)
pgbench اسکریپتهای آزمایشی را که بهصورت تصادفی از یک فهرست مشخص انتخاب شدهاند، اجرا میکند. این اسکریپتها میتوانند شامل اسکریپتهای توکار مشخصشده با -b و اسکریپتهای ارائهشده توسط کاربر مشخصشده با -f باشند. به هر اسکریپت میتوان یک وزن نسبی اختصاص داد که پس از علامت @ مشخص میشود تا احتمال انتخاب آن تغییر کند. وزن پیشفرض 1 است. اسکریپتهای با وزن 0 نادیده گرفته میشوند.
اسکریپت تراکنش توکار پیشفرض (که با -b tpcb-like نیز فراخوانی میشود) در هر تراکنش هفت دستور را روی مقادیر تصادفی انتخابشده از aid، tid، bid و delta صادر میکند. این سناریو از بنچمارک TPC-B الهام گرفته شده است، اما در واقع خود TPC-B نیست، و نامگذاری آن نیز به همین دلیل است.
اگر اسکریپت توکار simple-update را انتخاب کنید (همچنین با -N)، مراحل 4 و 5 در تراکنش گنجانده نمیشوند. این کار از رقابت بهروزرسانی بر روی این جدولها جلوگیری میکند، اما مورد آزمایشی را حتی کمتر از قبل شبیه TPC-B میسازد.
اگر اسکریپت توکار select-only را انتخاب کنید (همچنین با -S)، تنها دستور SELECT صادر میشود.
اسکریپتهای سفارشی (Custom Scripts)
ابزار pgbench از اجرای سناریوهای محک (benchmark) سفارشی از طریق جایگزین کردن اسکریپت تراکنش پیشفرض (توصیفشده در بالا) با یک اسکریپت تراکنش خواندهشده از فایل (گزینه -f) پشتیبانی میکند. در این حالت یک “تراکنش” معادل یک بار اجرای فایل اسکریپت در نظر گرفته میشود.
یک فایل اسکریپت شامل یک یا چند دستور SQL است که با نقطه-ویرگول خاتمه مییابند. خطوط خالی و خطوطی که با -- شروع میشوند نادیده گرفته میشوند. همچنین فایلهای اسکریپت میتوانند شامل “دستورهای متا” باشند که همانطور که در ادامه شرح داده شده است توسط خود pgbench تفسیر میشوند.
نکته
پیش از PostgreSQL نسخه 9.6، دستورهای SQL در فایلهای اسکریپت با خطوط جدید خاتمه مییافتند و بنابراین نمیتوانستند در چندین خط ادامه یابند. اکنون برای جداسازی دستورهای متوالی SQL استفاده از نقطه-ویرگول الزامی است (اگرچه در صورتی که پس از یک دستور SQL یک دستور متا بیاید، نیازی به نقطه-ویرگول نیست). اگر نیاز به ایجاد یک فایل اسکریپت دارید که با هر دو نسخه قدیمی و جدید pgbench کار کند، حتماً هر دستور SQL را روی یک خط مجزا و ختم به نقطه-ویرگول بنویسید.
فرض بر این است که اسکریپتهای pgbench شامل بلوکهای ناقص از تراکنشهای SQL نیستند. اگر در زمان اجرا کلاینت بدون تکمیل آخرین بلوک تراکنش به انتهای اسکریپت برسد، لغو (abort) خواهد شد.
یک قابلیت ساده برای جایگزینی متغیرها در فایلهای اسکریپت وجود دارد. نام متغیرها باید شامل حروف (از جمله حروف غیرلاتین)، ارقام و خط زیر (underscore) باشد، بهطوری که کاراکتر اول رقم نباشد. متغیرها را میتوان با گزینه خط فرمان -D که در بالا توضیح داده شد، یا با دستورهای متا که در ادامه شرح داده میشوند، مقداردهی کرد. علاوه بر متغیرهایی که از قبل با گزینههای خط فرمان -D تنظیم شدهاند، چند متغیر وجود دارند که بهطور خودکار مقداردهی اولیه میشوند و در Table 301 فهرست شدهاند. مقداری که با استفاده از -D برای این متغیرها مشخص شود، بر مقادیر خودکار پیشفرض تقدم دارد. پس از تنظیم، مقدار یک متغیر را میتوان با نوشتن :variablename درون یک دستور SQL درج کرد. هنگام اجرای بیش از یک نشست کلاینت، هر نشست مجموعه متغیرهای خاص خود را دارد. pgbench تا ۲۵۵ بار استفاده از متغیر را در یک دستور پشتیبانی میکند.
Table 301. pgbench Automatic Variables
| Variable | توضیحات |
| client_id | شماره یکتای شناسایی نشست کلاینت (از صفر شروع میشود) |
| default_seed | سید پیشفرض استفادهشده در توابع هش و جایگشت شبهتصادفی |
| random_seed | سید مولد تصادفی (مگر اینکه با -D بازنویسی شود) |
| scale | ضریب مقیاس فعلی |
دستورهای
متای فایل
اسکریپت با
یک بکاسلش
(\) آغاز
میشوند و
بهطور
معمول تا
انتهای خط
امتداد
مییابند،
اگرچه
میتوان با
نوشتن
بکاسلش-اینتر
(backslash-return) آنها را
در خطوط
بعدی نیز
ادامه داد.
آرگومانهای
یک دستور
متا با
فاصله (white space) از
هم جدا
میشوند.
این
دستورهای
متا
پشتیبانی
میشوند:
\gset [prefix] \aset [prefix]
هنگامی که دستور \gset استفاده میشود، انتظار میرود پرسوجوی SQL قبلی یک سطر بازگرداند؛ ستونهای این سطر در متغیرهایی به نام همان ستونها ذخیره میشوند و در صورت مشخص شدن prefix، پیشوند مذکور به ابتدای آنها اضافه میشود.
هنگامی که دستور \aset استفاده میشود، تمام پرسوجوهای ترکیبی SQL (که با \; از هم جدا شدهاند) ستونهایشان در متغیرهایی همنام با ستونها ذخیره میشود و در صورت تعیین prefix، این پیشوند به ابتدای آنها افزوده میشود. اگر یک پرسوجو هیچ سطری بازنگرداند، هیچ مقداری تخصیص داده نمیشود و برای تشخیص این حالت میتوان وجود متغیر را بررسی کرد. اگر یک پرسوجو بیش از یک سطر بازگرداند، مقدار آخرین سطر حفظ میشود.
دستورهای \gset و \aset نمیتوانند در حالت خطلولهای (pipeline mode) استفاده شوند، زیرا نتایج پرسوجو در زمانی که دستورها به آنها نیاز دارند هنوز در دسترس نیستند.
مثال زیر موجودی نهایی حساب را از پرسوجوی اول در متغیر abalance قرار میدهد و متغیرهای p_two و p_three را با اعداد صحیح حاصل از پرسوجوی سوم پر میکند. نتیجه پرسوجوی دوم نادیده گرفته میشود. نتایج حاصل از دو پرسوجوی ترکیبی آخر نیز در متغیرهای four و five ذخیره میشوند.
UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid RETURNING abalance \gset -- compound of two queries SELECT 1 \; SELECT 2 AS two, 3 AS three \gset p_ SELECT 4 AS four \; SELECT 5 AS five \aset
\if expression
\elif expression
\else
\endif
\set varname expression
توابع و اغلب عملگرها در ازای ورودی NULL، مقدار NULL بازمیگردانند.
برای مقاصد شرطی، مقادیر عددی غیرصفر معادل TRUE بوده و مقادیر عددی صفر و NULL معادل FALSE هستند.
ثابتهای عدد صحیح و ممیز شناور (double) بسیار بزرگ یا بسیار کوچک، و همچنین عملگرهای محاسباتی اعداد صحیح (+، -, * و /) در صورت سرریز (overflow) خطا تولید میکنند.
هنگامی که هیچ بند پایانی ELSE برای عبارت CASE تعیین نشده باشد، مقدار پیشفرض NULL است.
مثالها:
\set ntellers 10 * :scale
\set aid (1021 * random(1, 100000 * :scale)) % \
(100000 * :scale) + 1
\set divx CASE WHEN :x <> 0 THEN :y/:x ELSE NULL END
\sleep number [ us | ms | s ]
مثال:
\sleep 10 ms
\setshell varname command [ argument ... ]
command و هر argument میتواند یک ثابت متنی یا یک ارجاع :variablename به یک متغیر باشد. اگر میخواهید از یک argument استفاده کنید که با دونقطه شروع میشود، یک دونقطه دیگر در ابتدای argument بنویسید.
مثال:
\setshell variable_to_be_assigned command literal_argument :variable ::literal_starting_with_colon
\shell command [ argument ... ]
مثال:
\shell command literal_argument :variable ::literal_starting_with_colon
\startpipeline
\syncpipeline
\endpipeline
عملگرهای داخلی (Built-in Operators)
عملگرهای حسابی، بیتی، مقایسهای و منطقی فهرستشده در Table 302 بهصورت توکار در pgbench پیادهسازی شدهاند و میتوان از آنها در عبارتهایی که در \set میآیند استفاده کرد. این عملگرها به ترتیب اولویت صعودی فهرست شدهاند. بهجز موارد قید شده، عملگرهایی که دو ورودی عددی میگیرند، در صورتی که هر یک از ورودیها از نوع اعشاری (double) باشد، مقداری از نوع double تولید میکنند؛ در غیر این صورت، نتیجه از نوع عدد صحیح (integer) خواهد بود.
Table 302. pgbench Operators
| Operator .PP توضیحات (Description) .PP Example(s) |
| boolean OR boolean → boolean .PP OR منطقی .PP 5 or 0 → TRUE |
| boolean AND boolean → boolean .PP AND منطقی .PP 3 and 0 → FALSE |
| NOT boolean → boolean .PP NOT منطقی .PP not false → TRUE |
| boolean IS [NOT] (NULL|TRUE|FALSE) → boolean .PP آزمونهای مقدار بولی (Boolean) .PP 1 is null → FALSE |
| value ISNULL|NOTNULL → boolean .PP آزمونهای تهی بودن (Nullness) .PP 1 notnull → TRUE |
| number = number → boolean .PP برابر .PP 5 = 4 → FALSE |
| number <> number → boolean .PP نابرابر .PP 5 <> 4 → TRUE |
| number != number → boolean .PP نابرابر .PP 5 != 5 → FALSE |
| number < number → boolean .PP کوچکتر از .PP 5 < 4 → FALSE |
| number <= number → boolean .PP کوچکتر یا مساوی با .PP 5 <= 4 → FALSE |
| number > number → boolean .PP بزرگتر از .PP 5 > 4 → TRUE |
| number >= number → boolean .PP بزرگتر یا مساوی با .PP 5 >= 4 → TRUE |
| integer | integer → integer .PP OR بیتی .PP 1 | 2 → 3 |
| integer # integer → integer .PP XOR بیتی .PP 1 # 3 → 2 |
| integer & integer → integer .PP AND بیتی .PP 1 & 3 → 1 |
| ~ integer → integer .PP NOT بیتی .PP ~ 1 → -2 |
| integer << integer → integer .PP شیفت بیتی به چپ .PP 1 << 2 → 4 |
| integer >> integer → integer .PP شیفت بیتی به راست .PP 8 >> 2 → 2 |
| number + number → number .PP جمع .PP 5 + 4 → 9 |
| number - number → number .PP تفریق .PP 3 - 2.0 → 1.0 |
| number * number → number .PP ضرب .PP 5 * 4 → 20 |
| number / number → number .PP تقسیم (اگر هر دو ورودی عدد صحیح باشند، نتیجه به سمت صفر قطع میشود) .PP 5 / 3 → 1 |
| integer % integer → integer .PP باقیمانده (Modulo) .PP 3 % 2 → 1 |
| - number → number .PP قرینهسازی (Negation) .PP - 2.0 → -2.0 |
توابع داخلی (Built-In Functions)
توابع
فهرستشده
در
Table 303 بهصورت
توکار در pgbench
پیادهسازی
شدهاند و
میتوان از
آنها در
عبارتهایی
که در \set
میآیند
استفاده
کرد.
Table 303. pgbench Functions
| Function .PP توضیحات (Description) .PP Example(s) |
| abs ( number ) → same type as input .PP مقدار مطلق .PP abs(-17) → 17 |
| debug ( number ) → same type as input .PP آرگومان را در stderr چاپ کرده و همان آرگومان را برمیگرداند. .PP debug(5432.1) → 5432.1 |
| double ( number ) → double .PP به نوع double تبدیل میکند. .PP double(5432) → 5432.0 |
| exp ( number ) → double .PP تابع نمایی (عدد e به توان مقدار دادهشده) .PP exp(1.0) → 2.718281828459045 |
| greatest ( number [, ... ] ) → double if any argument is double, else integer .PP بزرگترین مقدار را از میان آرگومانها انتخاب میکند. .PP greatest(5, 4, 3, 2) → 5 |
| hash ( value [, seed ] ) → integer .PP این یک نام مستعار برای hash_murmur2 است. .PP hash(10, 5432) → -5817877081768721676 |
| hash_fnv1a ( value [, seed ] ) → integer .PP هش FNV-1a را محاسبه میکند. .PP hash_fnv1a(10, 5432) → -7793829335365542153 |
| hash_murmur2 ( value [, seed ] ) → integer .PP هش MurmurHash2 را محاسبه میکند. .PP hash_murmur2(10, 5432) → -5817877081768721676 |
| int ( number ) → integer .PP به نوع integer تبدیل میکند. .PP int(5.4 + 3.8) → 9 |
| least ( number [, ... ] ) → double if any argument is double, else integer .PP کوچکترین مقدار را از میان آرگومانها انتخاب میکند. .PP least(5, 4, 3, 2.1) → 2.1 |
| ln ( number ) → double .PP لگاریتم طبیعی .PP ln(2.718281828459045) → 1.0 |
| mod ( integer, integer ) → integer .PP باقیمانده تقسیم (Modulo) .PP mod(54, 32) → 22 |
| permute ( i, size [, seed ] ) → integer .PP مقدار جایگشتیافتهی i در بازه [0, size). این موقعیت جدید i (به پیمانهی size) در یک جایگشت شبهتصادفی از اعداد صحیح 0...size-1 با پارامتر seed است؛ به پایین مراجعه کنید. .PP permute(0, 4) → an integer between 0 and 3 |
| pi () → double .PP مقدار تقریبی π .PP pi() → 3.14159265358979323846 |
| pow ( x, y ) → double .PP power ( x, y ) → double .PP x به توان y .PP pow(2.0, 10) → 1024.0 |
| random ( lb, ub ) → integer .PP یک عدد صحیح تصادفی با توزیع یکنواخت در بازه [lb, ub] محاسبه میکند. .PP random(1, 10) → an integer between 1 and 10 |
| random_exponential ( lb, ub, parameter ) → integer .PP یک عدد صحیح تصادفی با توزیع نمایی در بازه [lb, ub] محاسبه میکند؛ به پایین مراجعه کنید. .PP random_exponential(1, 10, 3.0) → an integer between 1 and 10 |
| random_gaussian ( lb, ub, parameter ) → integer .PP یک عدد صحیح تصادفی با توزیع گاوسی در بازه [lb, ub] محاسبه میکند؛ به پایین مراجعه کنید. .PP random_gaussian(1, 10, 2.5) → an integer between 1 and 10 |
| random_zipfian ( lb, ub, parameter ) → integer .PP یک عدد صحیح تصادفی با توزیع زیپف در بازه [lb, ub] محاسبه میکند؛ به پایین مراجعه کنید. .PP random_zipfian(1, 10, 1.5) → an integer between 1 and 10 |
| sqrt ( number ) → double .PP ریشه دوم (جذر) .PP sqrt(2.0) → 1.414213562 |
تابع
random مقادیر
را با
استفاده از
توزیع
یکنواخت
تولید
میکند؛ به
این معنی که
تمام
مقادیر در
محدوده
تعیینشده
با احتمال
برابر
انتخاب
میشوند.
توابع random_exponential،
random_gaussian و random_zipfian
نیازمند یک
پارامتر
اعشاری
مضاعف (double)
اضافی
هستند که
شکل دقیق
توزیع را
تعیین
میکند.
f(x) = exp(-parameter * (x - min) / (max - min + 1)) / (1 - exp(-parameter))
آنگاه مقدار i بین min و max (شامل هر دو) با احتمال زیر انتخاب میشود: f(i) - f(i + 1).
بهطور شهودی، هرچه parameter بزرگتر باشد، مقادیر نزدیک به min با بسامد بیشتری مورد دسترسی قرار میگیرند، و مقادیر نزدیک به max با بسامد کمتری دسترسی مییابند. هرچه parameter به 0 نزدیکتر باشد، توزیع دسترسی مسطحتر (یکنواختتر) خواهد بود. یک تقریب سرانگشتی از توزیع این است که ۱٪ پربسامدترین مقادیر در محدوده، نزدیک به min، در parameter٪ از مواقع انتخاب میشوند. مقدار parameter باید اکیداً مثبت باشد.
f(x) = PHI(2.0 * parameter * (x - mu) / (max - min + 1)) /
(2.0 * PHI(parameter) - 1)
آنگاه مقدار i بین min و max (شامل هر دو) با احتمال زیر انتخاب میشود: f(i + 0.5) - f(i - 0.5). بهطور شهودی، هرچه parameter بزرگتر باشد، مقادیر نزدیک به میانه بازه با بسامد بیشتری انتخاب میشوند، و مقادیر نزدیک به کرانهای min و max با بسامد کمتری انتخاب میگردند. حدود ۶۷٪ از مقادیر از میانه 1.0 / parameter، یعنی به نسبت 0.5 / parameter در اطراف میانگین، و ۹۵٪ در میانه 2.0 / parameter، یعنی به نسبت 1.0 / parameter در اطراف میانگین انتخاب میشوند؛ برای مثال، اگر parameter برابر 4.0 باشد، ۶۷٪ مقادیر از یکچهارم میانی (1.0 / 4.0) بازه (یعنی از 3.0 / 8.0 تا 5.0 / 8.0) و ۹۵٪ از نیمه میانی (2.0 / 4.0) بازه (چارکهای دوم و سوم) انتخاب میشوند. کمترین مقدار مجاز برای parameter برابر 2.0 است.
پیادهسازی pgbench بر اساس مرجع "Non-Uniform Random Variate Generation" نوشته Luc Devroye، صفحات ۵۵۰-۵۵۱، انتشارات Springer سال ۱۹۸۶ است. به دلیل محدودیتهای آن الگوریتم، مقدار parameter به بازه [1.001, 1000] محدود شده است.
نکته
هنگام طراحی یک بنچمارک که سطرها را بهطور غیریکنواخت انتخاب میکند، آگاه باشید سطرهای انتخابشده ممکن است با سایر دادهها مانند شناسههای حاصل از یک دنباله یا ترتیب فیزیکی سطرها همبستگی داشته باشند، که این امر میتواند اندازهگیریهای عملکرد را منحرف کند.
برای جلوگیری از این امر، ممکن است بخواهید از تابع permute یا مراحل تکمیلی دیگر با اثری مشابه استفاده کنید تا سطرهای انتخابی را بُر بزنید (shuffle) و چنین همبستگیهایی را حذف نمایید.
توابع هش hash، hash_murmur2 و hash_fnv1a یک مقدار ورودی و یک پارامتر بذر (seed) اختیاری میپذیرند. در صورتی که بذر تعیین نشود، مقدار :default_seed استفاده میشود که بهطور تصادفی مقداردهی اولیه میگردد، مگر اینکه با گزینه -D خط فرمان تنظیم شده باشد.
تابع permute یک مقدار ورودی، یک اندازه، و یک پارامتر بذر اختیاری میپذیرد. این تابع یک جایگشت شبهتصادفی از اعداد صحیح در محدوده [0, size) تولید کرده و نمایه (index) مقدار ورودی را در میان مقادیر جایگشتیافته برمیگرداند. جایگشت انتخابشده توسط بذر پارامترسازی میشود که در صورت عدم تعیین، بهطور پیشفرض :default_seed است. برخلاف توابع هش، permute تضمین میکند که هیچ تداخل (collision) یا شکافی در مقادیر خروجی وجود نداشته باشد. مقادیر ورودی خارج از بازه بر مبنای باقیمانده تقسیم بر اندازه (modulo size) تفسیر میشوند. اگر اندازه مثبت نباشد، تابع یک خطا صادر میکند.
permute میتواند برای پراکنده ساختن توزیع توابع تصادفی غیریکنواخت مانند random_zipfian یا random_exponential بهکار رود تا مقادیری که بیشتر انتخاب میشوند همبستگی آشکاری با یکدیگر نداشته باشند. برای مثال، اسکریپت pgbench زیر یک بار کاری واقعی احتمالی را شبیهسازی میکند که برای شبکههای اجتماعی و پلتفرمهای وبلاگنویسی معمول است؛ جایی که تعداد کمی از حسابها بار کاری بسیار زیادی ایجاد میکنند:
\set size 1000000 \set r random_zipfian(1, :size, 1.07) \set k 1 + permute(:r, :size)
در برخی موارد به چند توزیع متمایز نیاز است که با یکدیگر همبستگی نداشته باشند و در اینجاست که پارامتر بذر اختیاری به کار میآید:
\set k1 1 + permute(:r, :size, :default_seed + 123) \set k2 1 + permute(:r, :size, :default_seed + 321)
رفتار مشابهی را میتوان با hash نیز تقریب زد:
\set size 1000000 \set r random_zipfian(1, 100 * :size, 1.07) \set k 1 + abs(hash(:r)) % :size
با این حال، از آنجا که hash تداخل (collision) تولید میکند، برخی مقادیر در دسترس نخواهند بود و برخی دیگر با بسامدی بیش از آنچه از توزیع اصلی انتظار میرود رخ خواهند داد.
بهعنوان مثال، تعریف کامل تراکنش پیشساخته مشابه TPC-B عبارت است از:
\set aid random(1, 100000 * :scale) \set bid random(1, 1 * :scale) \set tid random(1, 10 * :scale) \set delta random(-5000, 5000) BEGIN; UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid; SELECT abalance FROM pgbench_accounts WHERE aid = :aid; UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid; UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid; INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP); END;
این اسکریپت به هر تکرار از تراکنش اجازه میدهد به سطرهای متفاوت و بهصورت تصادفی انتخابشده ارجاع دهد. (این مثال همچنین نشان میدهد چرا مهم است هر نشست کلاینت متغیرهای خاص خود را داشته باشد — در غیر این صورت آنها بهطور مستقل به سطرهای متفاوت دسترسی نخواهند داشت.)
ثبت وقایع بر اساس هر تراکنش (Per-Transaction Logging)
با گزینه -l (اما بدون گزینه --aggregate-interval)، برنامه pgbench اطلاعات مربوط به هر تراکنش را در یک فایل لاگ مینویسد. نام فایل لاگ به صورت prefix.nnn خواهد بود، که در آن prefix به طور پیشفرض pgbench_log است و nnn شناسه فرایند (PID) پردازش pgbench میباشد. پیشوند را میتوان با استفاده از گزینه --log-prefix تغییر داد. اگر گزینه -j برابر ۲ یا بیشتر باشد، به طوری که چندین رشته کاری (worker threads) وجود داشته باشد، هر کدام فایل لاگ اختصاصی خود را خواهند داشت. اولین worker از همان نامی برای فایل لاگ خود استفاده میکند که در حالت استاندارد تکworker استفاده میشود. فایلهای لاگ اضافی برای سایر workerها با الگوی prefix.nnn.mmm نامگذاری میشوند، که در آن mmm یک شماره ترتیبی برای هر worker است که از ۱ آغاز میشود.
هر خط در فایل لاگ، یک تراکنش را شرح میدهد. این خط شامل فیلدهای زیر است که با فاصله از هم جدا شدهاند:
client_id
transaction_no
time
script_no
time_epoch
time_us
schedule_lag
retries
هنگامی که هر دو گزینه --rate و --latency-limit استفاده شوند، مقدار time برای یک تراکنش نادیدهگرفتهشده به صورت skipped گزارش میشود. اگر تراکنش با شکست خاتمه یابد، مقدار time آن به صورت failed گزارش خواهد شد. اگر از گزینه --failures-detailed استفاده کنید، مقدار time تراکنش ناموفق بر اساس نوع خطا به صورت serialization یا deadlock گزارش خواهد شد (برای اطلاعات بیشتر به بخش Failures and Serialization/Deadlock Retries مراجعه فرمایید).
در اینجا نمونهای از فایل لاگ تولیدشده در یک اجرای تککلاینتی آورده شده است:
0 199 2241 0 1175850568 995598 0 200 2465 0 1175850568 998079 0 201 2513 0 1175850569 608 0 202 2038 0 1175850569 2663
مثالی دیگر با --rate=100 و --latency-limit=5 (به ستون اضافی schedule_lag توجه کنید):
0 81 4621 0 1412881037 912698 3005 0 82 6173 0 1412881037 914578 4304 0 83 skipped 0 1412881037 914578 5217 0 83 skipped 0 1412881037 914578 5099 0 83 4722 0 1412881037 916203 3108 0 84 4142 0 1412881037 918023 2333 0 85 2465 0 1412881037 919759 740
در این مثال، تراکنش ۸۲ با تاخیر مواجه شد، زیرا زمان تاخیر آن (۶.۱۷۳ میلیثانیه) فراتر از محدودیت ۵ میلیثانیه بود. دو تراکنش بعدی نادیده گرفته شدند (skipped)، زیرا پیش از آنکه حتی آغاز شوند، بیش از حد به تاخیر افتاده بودند.
مثال زیر بخشی از یک فایل لاگ به همراه خطاها و تلاشهای مجدد را نشان میدهد، که در آن حداکثر تعداد تلاشها روی ۱۰ تنظیم شده است (به ستون اضافی retries توجه کنید):
3 0 47423 0 1499414498 34501 3 3 1 8333 0 1499414498 42848 0 3 2 8358 0 1499414498 51219 0 4 0 72345 0 1499414498 59433 6 1 3 41718 0 1499414498 67879 4 1 4 8416 0 1499414498 76311 0 3 3 33235 0 1499414498 84469 3 0 0 failed 0 1499414498 84905 9 2 0 failed 0 1499414498 86248 9 3 4 8307 0 1499414498 92788 0
اگر گزینه --failures-detailed استفاده شود، نوع خطا در ستون time به صورت زیر گزارش میشود:
3 0 47423 0 1499414498 34501 3 3 1 8333 0 1499414498 42848 0 3 2 8358 0 1499414498 51219 0 4 0 72345 0 1499414498 59433 6 1 3 41718 0 1499414498 67879 4 1 4 8416 0 1499414498 76311 0 3 3 33235 0 1499414498 84469 3 0 0 serialization 0 1499414498 84905 9 2 0 serialization 0 1499414498 86248 9 3 4 8307 0 1499414498 92788 0
هنگام اجرای یک آزمایش طولانی روی سختافزاری که توانایی پردازش تعداد بالایی از تراکنشها را دارد، حجم فایلهای لاگ ممکن است بسیار زیاد شود. با استفاده از گزینه --sampling-rate میتوان تنها یک نمونهبرداری تصادفی از تراکنشها را ثبت کرد.
ثبت وقایع تجمیعی (Aggregated Logging)
با گزینه --aggregate-interval، قالب متفاوتی برای فایلهای لاگ به کار گرفته میشود. هر خط از فایل لاگ یک بازه تجمیعی را شرح میدهد. این خط شامل فیلدهای زیر است که با فاصله از هم جدا شدهاند:
interval_start
num_transactions
sum_latency
sum_latency_2
min_latency
max_latency
sum_lag
sum_lag_2
min_lag
max_lag
skipped
retried
retries
serialization_failures
deadlock_failures
در اینجا نمونهای از خروجی تولیدشده با این گزینه آورده شده است:
pgbench --aggregate-interval=10 --time=20 --client=10 --log --rate=1000 --latency-limit=10 --failures-detailed --max-tries=10 test 1650260552 5178 26171317 177284491527 1136 44462 2647617 7321113867 0 9866 64 7564 28340 4148 0 1650260562 4808 25573984 220121792172 1171 62083 3037380 9666800914 0 9998 598 7392 26621 4527 0
توجه کنید در حالی که قالب لاگ ساده (غیرتجمیعی) نشان میدهد چه اسکریپتی برای هر تراکنش استفاده شده است، قالب تجمیعی این کار را نمیکند. بنابراین اگر به دادههای تفکیکشده بر اساس هر اسکریپت نیاز دارید، باید دادهها را شخصاً تجمیع کنید.
گزارش به ازای هر دستور (Per-Statement Report)
با استفاده از گزینه -r ، pgbench آمارهای زیر را برای هر دستور جمعآوری میکند:
این گزارش آمارهای تلاش مجدد را تنها در صورتی نمایش میدهد که گزینه --max-tries برابر با ۱ نباشد.
تمام مقادیر برای هر دستور اجراشده توسط هر کلاینت محاسبه شده و پس از پایان آزمون محک گزارش میشوند.
برای اسکریپت پیشفرض، خروجی مشابه زیر خواهد بود:
starting vacuum...end. transaction type: <builtin: TPC-B (sort of)> scaling factor: 1 query mode: simple number of clients: 10 number of threads: 1 maximum number of tries: 1 number of transactions per client: 1000 number of transactions actually processed: 10000/10000 number of failed transactions: 0 (0.000%) number of transactions above the 50.0 ms latency limit: 1311/10000 (13.110 %) latency average = 28.488 ms latency stddev = 21.009 ms initial connection time = 69.068 ms tps = 346.224794 (without initial connection time) statement latencies in milliseconds and failures: 0.012 0 \set aid random(1, 100000 * :scale) 0.002 0 \set bid random(1, 1 * :scale) 0.002 0 \set tid random(1, 10 * :scale) 0.002 0 \set delta random(-5000, 5000) 0.319 0 BEGIN; 0.834 0 UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid; 0.641 0 SELECT abalance FROM pgbench_accounts WHERE aid = :aid; 11.126 0 UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid; 12.961 0 UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid; 0.634 0 INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP); 1.957 0 END;
مثال دیگری از خروجی برای اسکریپت پیشفرض با استفاده از سطح انزوای پیشفرض سریالپذیر تراکنش (PGOPTIONS='-c default_transaction_isolation=serializable' pgbench ...):
starting vacuum...end. transaction type: <builtin: TPC-B (sort of)> scaling factor: 1 query mode: simple number of clients: 10 number of threads: 1 maximum number of tries: 10 number of transactions per client: 1000 number of transactions actually processed: 6317/10000 number of failed transactions: 3683 (36.830%) number of transactions retried: 7667 (76.670%) total number of retries: 45339 number of transactions above the 50.0 ms latency limit: 106/6317 (1.678 %) latency average = 17.016 ms latency stddev = 13.283 ms initial connection time = 45.017 ms tps = 186.792667 (without initial connection time) statement latencies in milliseconds, failures and retries: 0.006 0 0 \set aid random(1, 100000 * :scale) 0.001 0 0 \set bid random(1, 1 * :scale) 0.001 0 0 \set tid random(1, 10 * :scale) 0.001 0 0 \set delta random(-5000, 5000) 0.385 0 0 BEGIN; 0.773 0 1 UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid; 0.624 0 0 SELECT abalance FROM pgbench_accounts WHERE aid = :aid; 1.098 320 3762 UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid; 0.582 3363 41576 UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid; 0.465 0 0 INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP); 1.933 0 0 END;
اگر چندین فایل اسکریپت مشخص شده باشد، تمامی آمارها برای هر فایل اسکریپت بهطور جداگانه گزارش میشوند.
توجه داشته باشید که جمعآوری اطلاعات زمانبندی اضافی مورد نیاز برای محاسبه تاخیر به ازای هر دستور، مقداری بار اضافی (overhead) تحمیل میکند. این امر سرعت میانگین اجرا را کاهش داده و TPS محاسبهشده را پایین میآورد. میزان این افت سرعت بسته به پلتفرم و سختافزار تفاوت چشمگیری دارد. مقایسه مقادیر میانگین TPS در دو حالت فعال بودن و غیرفعال بودن گزارش تاخیر، روش مناسبی برای ارزیابی قابلتوجه بودن بار اضافی زمانبندی است.
شکستها و تلاشهای مجدد در خطاهای سریالسازی/بنبست (Failures and Serialization/Deadlock Retries)
هنگام اجرای pgbench ، سه نوع اصلی از خطاها وجود دارند:
اجرای یک کلاینت در صورت بروز یک خطای جدی لغو میشود؛ به عنوان مثال، اتصال با سرور پایگاه داده قطع شود یا پایان اسکریپت بدون تکمیل آخرین تراکنش فرا برسد. علاوه بر این، اگر اجرای یک دستور SQL یا یک متادستور به دلایلی غیر از خطاهای سریالسازی یا بنبست با شکست مواجه شود، کلاینت لغو میگردد. در غیر این صورت، چنانچه یک دستور SQL با خطاهای سریالسازی یا بنبست مواجه شود، کلاینت لغو نخواهد شد. در چنین حالتهایی، تراکنش جاری به عقب بازگردانده میشود (rollback)، که شامل بازگرداندن متغیرهای کلاینت به وضعیت پیش از اجرای این تراکنش نیز میگردد (فرض بر این است که یک اسکریپت تراکنش تنها شامل یک تراکنش است؛ برای اطلاعات بیشتر به «تراکنش» اجرا شده در pgbench دقیقاً چیست؟ (What Is the "Transaction" Actually Performed in pgbench?) مراجعه کنید). تراکنشهای دارای خطای سریالسازی یا بنبست پس از rollback تکرار میشوند تا زمانی که با موفقیت به پایان برسند یا به حداکثر تعداد تلاشها (مشخصشده با گزینه --max-tries ) / حداکثر زمان تلاشهای مجدد (مشخصشده با گزینه --latency-limit ) / پایان آزمون محک (مشخصشده با گزینه --time ) برسند. اگر آخرین تلاش برای اجرا شکست بخورد، این تراکنش به عنوان ناموفق گزارش میشود اما کلاینت لغو نخواهد شد و به کار خود ادامه میدهد.
یادداشت (Note)
بدون تعیین گزینه --max-tries ، یک تراکنش پس از خطای سریالسازی یا بنبست هرگز دوباره تکرار نخواهد شد، زیرا مقدار پیشفرض آن ۱ است. از تعداد نامحدود تلاش (--max-tries=0) و گزینه --latency-limit استفاده کنید تا تنها حداکثر زمان تلاشها را محدود سازید. همچنین میتوانید از گزینه --time برای محدود کردن مدتزمان آزمون محک در شرایط تعداد نامحدود تلاش استفاده نمایید.
هنگام تکرار اسکریپتهایی که شامل چندین تراکنش هستند مراقب باشید: اسکریپت همواره بهطور کامل دوباره اجرا میشود، بنابراین ممکن است تراکنشهای موفق چندین بار انجام شوند.
هنگام تکرار تراکنشهای دارای دستورات پوسته (shell) مراقب باشید. برخلاف نتایج دستورات SQL، نتایج دستورات پوسته به عقب بازگردانده نمیشوند (roll back نمیشوند)، به جز مقدار متغیر دستور \setshell .
تاخیر یک تراکنش موفق شامل کل مدت زمان اجرای تراکنش همراه با بازگردانیها (rollbacks) و تلاشهای مجدد است. تاخیر فقط برای تراکنشها و دستورات موفق اندازهگیری میشود، نه برای تراکنشها یا دستورات ناموفق.
گزارش اصلی شامل تعداد تراکنشهای ناموفق است. اگر گزینه --max-tries مخالف ۱ باشد، گزارش اصلی همچنین شامل آمار مربوط به تلاشهای مجدد خواهد بود: تعداد کل تراکنشهای بازآزمودهشده و تعداد کل تلاشهای مجدد. گزارش به ازای هر اسکریپت تمام این فیلدها را از گزارش اصلی به ارث میبرد. گزارش به ازای هر دستور آمار تلاش مجدد را تنها در صورتی نمایش میدهد که گزینه --max-tries مخالف ۱ باشد.
اگر میخواهید شکستها را بر اساس انواع پایه در لاگهای به ازای تراکنش و تجمیعی، و همچنین در گزارشهای اصلی و به ازای اسکریپت دستهبندی کنید، از گزینه --failures-detailed استفاده کنید. اگر میخواهید همه خطاها و شکستها (خطاهای بدون تلاش مجدد) را بر اساس نوع تفکیک کنید، شامل اینکه کدام حد مجاز برای تلاشهای مجدد رد شده است و برای شکستهای سریالسازی/بنبست چقدر از آن حد فراتر رفته است، از گزینه --verbose-errors استفاده نمایید.
روشهای دسترسی به جدول (Table Access Methods)
شما میتوانید روش دسترسی به جدول (Table Access Method) را برای جداول pgbench مشخص کنید. متغیر محیطی PGOPTIONS گزینههای پیکربندی پایگاه داده را که از طریق خط فرمان به PostgreSQL ارسال میشوند، تعیین میکند (بخش Section 19.1.4 را ببینید). برای نمونه، یک روش فرضی دسترسی به جدول پیشفرض برای جداولی که pgbench ایجاد میکند به نام wuzza را میتوان با دستور زیر مشخص کرد:
PGOPTIONS='-c default_table_access_method=wuzza'
روشهای بهینه و توصیهها (Good Practices)
تولید اعداد و ارقام کاملاً بیمعنی با استفاده از pgbench بسیار آسان است. در اینجا چند دستورالعمل برای کمک به دریافت نتایج مفید آورده شده است.
در وهله نخست، هرگز به آزمونی که تنها چند ثانیه اجرا میشود اعتماد نکنید. از گزینه -t یا -T استفاده کنید تا اجرای آزمون حداقل چند دقیقه طول بکشد و نوسانات و نویزها به صورت میانگین تعدیل شوند. در برخی موارد ممکن است برای دستیابی به اعدادی که تکرارپذیر باشند، به ساعتها زمان نیاز داشته باشید. ایده خوبی است که اجرای آزمون را چند بار امتحان کنید تا مشخص شود که آیا اعداد بهدستآمده تکرارپذیر هستند یا خیر.
برای سناریوی آزمایشی پیشفرض مشابه TPC-B، ضریب مقیاس مقداردهی اولیه (-s) باید حداقل به بزرگی بیشترین تعداد کلاینتهایی باشد که قصد آزمایش آنها را دارید (-c)؛ در غیر این صورت، عمدتاً در حال اندازهگیری رقابت بر سر بهروزرسانی (update contention) خواهید بود. در جدول pgbench_branches تنها به تعداد -s ردیف وجود دارد، و هر تراکنش میخواهد یکی از آنها را بهروزرسانی کند، بنابراین مقادیر -c بیشتر از -s بدون شک منجر به مسدود شدن بسیاری از تراکنشها در انتظار سایر تراکنشها خواهد شد.
سناریوی آزمون پیشفرض همچنین نسبت به مدتزمانی که از مقداردهی اولیه جدولها گذشته بسیار حساس است: انباشت ردیفهای مرده (dead rows) و فضای خالی در جدولها نتایج را تغییر میدهد. برای درک درست نتایج، باید تعداد کل بهروزرسانیها و زمان انجام عملیات پاکسازی (vacuuming) را زیر نظر داشته باشید. در صورت فعال بودن autovacuum، ممکن است تغییرات غیرقابل پیشبینی در کارایی اندازهگیریشده رخ دهد.
یکی از محدودیتهای pgbench این است که هنگام آزمایش تعداد زیادی از نشستهای کلاینت، خودش میتواند به یک گلوگاه (bottleneck) تبدیل شود. این مشکل را میتوان با اجرای pgbench روی ماشینی مجزا از سرور پایگاه داده کاهش داد، هرچند تاخیر پایین شبکه (low network latency) در این حالت ضروری خواهد بود. حتی ممکن است اجرای همزمان چندین نمونه از pgbench روی چندین ماشین کلاینت علیه یک سرور پایگاه داده مفید باشد.
امنیت (Security)
اگر کاربران غیرقابلاعتماد به پایگاه دادهای دسترسی دارند که از الگوی استفاده از شمای امن (secure schema usage pattern) پیروی نکرده است، pgbench را در آن پایگاه داده اجرا نکنید. pgbench از نامهای واجد شرایط نشده (unqualified names) استفاده میکند و مسیر جستجو (search path) را دستکاری نمیکند.
| 2026 | PostgreSQL 18.6 |