آموزش جامع متغیر سیستمی @@CPU_BUSY در SQL Server با ۱۰ مثال عملی
هنگامی که یک گزارش فنی باید هم برای DBA و هم برای توسعهدهنده قابل استفاده باشد، انتخاب تابع کمکی درست اهمیت زیادی پیدا میکند. در این مقاله، @@CPU_BUSY از سطح مقدماتی تا سناریوهای حرفهای بررسی میشود و هر مثال با خروجی نمونه ارائه شده است.
با نمونهبرداری دورهای و محاسبه اختلاف میتوان روند کلی فعالیت CPU موتور را سنجید، هرچند برای تحلیل دقیق Query کافی نیست. تمرکز آموزش بر این است که @@CPU_BUSY در چه Contextی اجرا شود، نتیجه آن چگونه تفسیر شود و چه زمانی باید از یک DMV یا کاتالوگویوی جایگزین کمک گرفت.
برای مشاهده جایگاه @@CPU_BUSY میان سایر توابع و شمارندهها، راهنمای جامع توابع کمکی کارایی و Metadata در SQL Server را نیز مطالعه کنید.
تعریف و کاربرد اصلی @@CPU_BUSY
متغیر @@CPU_BUSY تعداد Tickهای CPU مصرفشده توسط SQL Server از آخرین راهاندازی سرویس را بهصورت تجمعی گزارش میکند. این تعریف در ظاهر کوتاه است، اما استفاده درست از @@CPU_BUSY به درک مفاهیمی مانند CPU ticks، cumulative counter و @@TIMETICKS وابسته است.
قاعده عملی @@CPU_BUSY: ابتدا ورودی و Context را معتبر کنید، سپس خروجی را با نوع داده و معنای واقعی آن تفسیر کنید.
Syntax تابع یا متغیر @@CPU_BUSY
SELECT @@CPU_BUSY AS Result;
پارامترهای @@CPU_BUSY
| پارامتر | توضیح |
|---|
| بدون پارامتر | مقدار تجمعی Instance را برمیگرداند. |
نوع خروجی و رفتار NULL در @@CPU_BUSY
integer شمارنده Tick؛ برای تبدیل به میکروثانیه از @@TIMETICKS و برای تحلیل نرخ از اختلاف دو Snapshot استفاده میشود. در کد تولیدی بهتر است نوع مقصد بهصورت صریح تعیین شود؛ زیرا تبدیل ضمنی میتواند مقایسه، مرتبسازی یا ذخیره نتیجه @@CPU_BUSY را مبهم کند.
مفاهیم کلیدی مرتبط با @@CPU_BUSY
- CPU ticks
- cumulative counter در مبحث @@CPU_BUSY
- @@TIMETICKS در مبحث @@CPU_BUSY
- baseline در مبحث @@CPU_BUSY
- snapshot در مبحث @@CPU_BUSY
- instance uptime
- performance
تصویر نخست، ارتباط @@CPU_BUSY را با مفاهیم اختصاصی CPU ticks، cumulative counter، @@TIMETICKS و baseline نشان میدهد؛ این روابط مبنای انتخاب ورودی و تفسیر خروجی هستند.
سناریوهای واقعی استفاده از @@CPU_BUSY
سناریوی 1 برای @@CPU_BUSY، «Baseline سبک» است. در این حالت باید نتیجه همراه Context پایگاه داده، زمان نمونهبرداری و در صورت نیاز شناسه نشست ثبت شود تا داده برای عیبیابی بعدی ارزش داشته باشد.
سناریوی 2 برای @@CPU_BUSY، «مقایسه دو Snapshot» است. در این حالت باید نتیجه همراه Context پایگاه داده، زمان نمونهبرداری و در صورت نیاز شناسه نشست ثبت شود تا داده برای عیبیابی بعدی ارزش داشته باشد.
سناریوی 3 برای @@CPU_BUSY، «هشدار فعالیت غیرعادی» است. در این حالت باید نتیجه همراه Context پایگاه داده، زمان نمونهبرداری و در صورت نیاز شناسه نشست ثبت شود تا داده برای عیبیابی بعدی ارزش داشته باشد.
سناریوی 4 برای @@CPU_BUSY، «آموزش شمارندهها» است. در این حالت باید نتیجه همراه Context پایگاه داده، زمان نمونهبرداری و در صورت نیاز شناسه نشست ثبت شود تا داده برای عیبیابی بعدی ارزش داشته باشد.
مثالهای عملی @@CPU_BUSY از ساده تا حرفهای
مثال 1: خواندن مقدار پایه @@CPU_BUSY
شمارنده زمان تجمعی CPU را در لحظه فعلی میخوانیم. این سناریو بهطور اختصاصی برای درک رفتار @@CPU_BUSY طراحی شده است.
SELECT @@CPU_BUSY AS CurrentValue;
مقدار @@CPU_BUSY تجمعی است و بهتنهایی نرخ مصرف را نشان نمیدهد. هنگام استفاده سازمانی از @@CPU_BUSY، خروجی نمونه را با داده واقعی محیط خود تطبیق دهید.
مثال 2: ثبت Snapshot زماندار @@CPU_BUSY
مقدار زمان تجمعی CPU را همراه زمان نمونهبرداری ثبت میکنیم. این سناریو بهطور اختصاصی برای درک رفتار @@CPU_BUSY طراحی شده است.
SELECT @@CPU_BUSY AS CounterValue,
SYSDATETIME() AS CapturedAt,
sqlserver_start_time
FROM sys.dm_os_sys_info;
| CounterValue | CapturedAt | sqlserver_start_time |
|---|
| 1845200 | 2026-07-25 00:45:00 | 2026-07-20 08:00:00 |
زمان Startup مشخص میکند Baseline از چه نقطهای آغاز شده است. هنگام استفاده سازمانی از @@CPU_BUSY، خروجی نمونه را با داده واقعی محیط خود تطبیق دهید.
مثال 3: محاسبه اختلاف دو نمونه @@CPU_BUSY
برای زمان تجمعی CPU دو Snapshot میگیریم و Delta را محاسبه میکنیم. این سناریو بهطور اختصاصی برای درک رفتار @@CPU_BUSY طراحی شده است.
DECLARE @Before bigint = CONVERT(bigint, @@CPU_BUSY);
WAITFOR DELAY '00:00:01';
DECLARE @After bigint = CONVERT(bigint, @@CPU_BUSY);
SELECT @Before AS BeforeValue,
@After AS AfterValue,
@After - @Before AS DeltaValue;
| BeforeValue | AfterValue | DeltaValue |
|---|
| 1845200 | 1845222 | 22 |
Delta @@CPU_BUSY برای بازه مشخص قابل تفسیرتر از مقدار مطلق است. هنگام استفاده سازمانی از @@CPU_BUSY، خروجی نمونه را با داده واقعی محیط خود تطبیق دهید.
مثال 4: ذخیره @@CPU_BUSY در جدول موقت
برای پایش زمان تجمعی CPU یک جدول Snapshot کوچک میسازیم. این سناریو بهطور اختصاصی برای درک رفتار @@CPU_BUSY طراحی شده است.
CREATE TABLE #CounterSnapshot
(
CounterName sysname NOT NULL,
CounterValue bigint NOT NULL,
CapturedAt datetime2(3) NOT NULL
);
INSERT INTO #CounterSnapshot
VALUES (N'@@CPU_BUSY', CONVERT(bigint, @@CPU_BUSY), SYSDATETIME());
SELECT * FROM #CounterSnapshot;
| CounterName | CounterValue | CapturedAt |
|---|
| @@CPU_BUSY | 1845200 | 2026-07-25 00:46:00.000 |
ذخیره تاریخچه امکان محاسبه نرخ و تشخیص تغییر Baseline را فراهم میکند. هنگام استفاده سازمانی از @@CPU_BUSY، خروجی نمونه را با داده واقعی محیط خود تطبیق دهید.
تصویر دوم، جریان اجرای @@CPU_BUSY را از ورودی و اعتبارسنجی تا تولید خروجی نمایش میدهد و نشان میدهد که snapshot در کدام مرحله باید کنترل شود.
ادامه مثالهای پیشرفته @@CPU_BUSY
مثال 5: تبدیل @@CPU_BUSY به میکروثانیه
Tickهای زمان تجمعی CPU را با @@TIMETICKS به میکروثانیه تبدیل میکنیم. در این مثال، هدف تنها اجرای Query نیست؛ بلکه نشان دادن یک تصمیم فنی صحیح پیرامون @@CPU_BUSY است.
SELECT CONVERT(bigint, @@CPU_BUSY) * CONVERT(bigint, @@TIMETICKS)
AS TotalMicroseconds;
| TotalMicroseconds |
|---|
| 18452000000 |
CAST به bigint پیش از ضرب از Overflow نوع int جلوگیری میکند. این نکته از تفسیر سطحی یا استفاده تکراری و بیهدف از @@CPU_BUSY جلوگیری میکند.
مثال 6: تبدیل @@CPU_BUSY به ثانیه
مقدار زمان تجمعی CPU را به ثانیه قابل فهم تبدیل میکنیم. در این مثال، هدف تنها اجرای Query نیست؛ بلکه نشان دادن یک تصمیم فنی صحیح پیرامون @@CPU_BUSY است.
SELECT CAST(
CONVERT(decimal(38,0), @@CPU_BUSY) * @@TIMETICKS / 1000000.0
AS decimal(20,3)
) AS TotalSeconds;
این مقدار از Startup تجمعی است، نه مصرف یک Query خاص. این نکته از تفسیر سطحی یا استفاده تکراری و بیهدف از @@CPU_BUSY جلوگیری میکند.
مثال 7: جلوگیری از Overflow در @@CPU_BUSY
برای زمان تجمعی CPU نوع داده را پیش از محاسبات بزرگ ارتقا میدهیم. در این مثال، هدف تنها اجرای Query نیست؛ بلکه نشان دادن یک تصمیم فنی صحیح پیرامون @@CPU_BUSY است.
DECLARE @CounterValue int = @@CPU_BUSY;
SELECT CONVERT(bigint, @CounterValue) *
CONVERT(bigint, @@TIMETICKS) AS SafeMicroseconds;
| SafeMicroseconds |
|---|
| 18452000000 |
اگر ضرب با int انجام شود، شمارندههای بزرگ میتوانند خطای Overflow ایجاد کنند. این نکته از تفسیر سطحی یا استفاده تکراری و بیهدف از @@CPU_BUSY جلوگیری میکند.
مثال 8: مقایسه @@CPU_BUSY با @@IO_BUSY
برای تفسیر بهتر زمان تجمعی CPU یک شاخص مکمل را کنار آن میآوریم. در این مثال، هدف تنها اجرای Query نیست؛ بلکه نشان دادن یک تصمیم فنی صحیح پیرامون @@CPU_BUSY است.
SELECT CONVERT(bigint, @@CPU_BUSY) AS PrimaryCounter,
CONVERT(bigint, @@IO_BUSY) AS CompanionCounter,
SYSDATETIME() AS CapturedAt;
| PrimaryCounter | CompanionCounter | CapturedAt |
|---|
| 1845200 | 928400 | 2026-07-25 00:47:00 |
همبستگی دو شمارنده فقط سرنخ است و علت قطعی زمان تجمعی CPU را اثبات نمیکند. این نکته از تفسیر سطحی یا استفاده تکراری و بیهدف از @@CPU_BUSY جلوگیری میکند.
مثال 9: روش اشتباه در تفسیر @@CPU_BUSY
بهجای قضاوت بر اساس عدد مطلق زمان تجمعی CPU، Context زمانی را اضافه میکنیم. در این مثال، هدف تنها اجرای Query نیست؛ بلکه نشان دادن یک تصمیم فنی صحیح پیرامون @@CPU_BUSY است.
SELECT CONVERT(bigint, @@CPU_BUSY) AS AbsoluteValue,
DATEDIFF_BIG(second, sqlserver_start_time, SYSDATETIME()) AS UptimeSeconds
FROM sys.dm_os_sys_info;
| AbsoluteValue | UptimeSeconds |
|---|
| 1845200 | 414300 |
دو سرور با Uptime متفاوت را نباید فقط با مقدار تجمعی مقایسه کرد. این نکته از تفسیر سطحی یا استفاده تکراری و بیهدف از @@CPU_BUSY جلوگیری میکند.
مثال 10: Snapshot کمهزینه @@CPU_BUSY
برای زمان تجمعی CPU تنها ستونهای ضروری را در نمونهبرداری دورهای میخوانیم. در این مثال، هدف تنها اجرای Query نیست؛ بلکه نشان دادن یک تصمیم فنی صحیح پیرامون @@CPU_BUSY است.
SELECT
CONVERT(bigint, @@CPU_BUSY) AS CounterValue,
sqlserver_start_time,
SYSUTCDATETIME() AS CapturedAtUtc
FROM sys.dm_os_sys_info;
| CounterValue | sqlserver_start_time | CapturedAtUtc |
|---|
| 1845200 | 2026-07-20 08:00:00 | 2026-07-24 21:18:00 |
Query سبک است، اما Frequency جمعآوری و نگهداری تاریخچه باید منطقی باشد. این نکته از تفسیر سطحی یا استفاده تکراری و بیهدف از @@CPU_BUSY جلوگیری میکند.
خطاهای رایج در کار با @@CPU_BUSY
خطای 1 در استفاده از @@CPU_BUSY
مقدار تجمعی است و باید Delta محاسبه شود. برای رفع این مشکل، ورودی و Context را از منبع معتبر بخوانید و نتیجه @@CPU_BUSY را پیش از ادامه منطق با شرط صریح کنترل کنید.
خطای 2 در استفاده از @@CPU_BUSY
این شاخص CPU سیستمعامل یا هر Query را جداگانه نشان نمیدهد. برای رفع این مشکل، ورودی و Context را از منبع معتبر بخوانید و نتیجه @@CPU_BUSY را پیش از ادامه منطق با شرط صریح کنترل کنید.
خطای 3 در استفاده از @@CPU_BUSY
Restart سرویس Baseline را صفر میکند و احتمال Wraparound شمارنده باید در پایش بلندمدت لحاظ شود. برای رفع این مشکل، ورودی و Context را از منبع معتبر بخوانید و نتیجه @@CPU_BUSY را پیش از ادامه منطق با شرط صریح کنترل کنید.
ملاحظات Performance برای @@CPU_BUSY
از نظر کارایی، @@CPU_BUSY زمانی کمهزینه باقی میماند که روی یک مقدار هدفمند یا مجموعه محدود اجرا شود. فراخوانی آن روی هزاران ردیف بدون Predicate اولیه میتواند CPU و زمان گزارش را افزایش دهد.
اگر گزارش به چند Property از چندین شیء نیاز دارد، استفاده Set-based از کاتالوگویو یا DMV مرتبط با CPU ticks معمولاً بهتر از تکرار @@CPU_BUSY برای هر سلول است.
در Jobهای دورهای، نتیجه @@CPU_BUSY را همراه Timestamp ذخیره کنید، اما Frequency نمونهبرداری را متناسب با سرعت تغییر داده انتخاب کنید. جمعآوری بیش از حد، جدول تاریخچه را بدون ارزش تحلیلی بزرگ میکند.
برای محاسبات عددی پیرامون @@CPU_BUSY، نوع داده را قبل از ضرب یا تفریق ارتقا دهید و در سناریوهای تجمعی، Restart و بازنشانی Baseline را در نظر بگیرید.
Best Practiceهای اختصاصی @@CPU_BUSY
- ورودی @@CPU_BUSY را از نام یا شناسه معتبر و دارای Schema یا Context روشن تأمین کنید.
- نتیجه NULL در @@CPU_BUSY را از مقدار صفر، false یا رشته خالی جدا نگه دارید.
- نوع خروجی @@CPU_BUSY را پیش از ذخیره یا مقایسه به نوع مقصد مناسب تبدیل کنید.
- در گزارشهای بزرگ، گزینه Set-based مرتبط با CPU ticks را ارزیابی کنید.
- زمان Capture، نام Database و در صورت نیاز @@SPID را کنار نتیجه @@CPU_BUSY ثبت کنید.
- مجوز مشاهده Metadata یا DMV را با حداقل سطح دسترسی لازم تنظیم کنید. در مبحث @@CPU_BUSY
- مثالهای @@CPU_BUSY را روی نسخه و Edition واقعی محیط هدف آزمایش کنید.
- برای SQL پویا، خروجی نامی @@CPU_BUSY را با QUOTENAME و پارامترسازی ایمن مصرف کنید.
تصویر سوم، تفاوت روش پرخطر و Best Practice در استفاده از @@CPU_BUSY را مقایسه میکند؛ هدف آن جلوگیری از خطاهای مربوط به مقدار تجمعی است و باید Delta محاسبه شود. و بهبود تصمیمگیری فنی است.
سؤالات متداول اختصاصی @@CPU_BUSY
@@CPU_BUSY دقیقاً چه مسئلهای را در SQL Server حل میکند؟
متغیر @@CPU_BUSY تعداد Tickهای CPU مصرفشده توسط SQL Server از آخرین راهاندازی سرویس را بهصورت تجمعی گزارش میکند. در عمل، با نمونهبرداری دورهای و محاسبه اختلاف میتوان روند کلی فعالیت CPU موتور را سنجید، هرچند برای تحلیل دقیق Query کافی نیست. بنابراین استفاده از @@CPU_BUSY زمانی ارزشمند است که خروجی آن در یک تصمیم فنی روشن مصرف شود، نه اینکه فقط برای نمایش عدد یا نام به کار رود.
نوع خروجی @@CPU_BUSY چیست و چگونه باید آن را مدیریت کرد؟
نوع خروجی این ابزار چنین است: integer شمارنده Tick؛ برای تبدیل به میکروثانیه از @@TIMETICKS و برای تحلیل نرخ از اختلاف دو Snapshot استفاده میشود. بهتر است پیش از تبدیل نوع، مقایسه یا درج در جدول گزارش، حالت NULL و محدوده مقدار را صریح کنترل کنید تا رفتار @@CPU_BUSY قابل پیشبینی بماند.
آیا @@CPU_BUSY در گزارشهای سازمانی کاربرد تجاری دارد؟
بله. در سناریوهایی مانند Baseline سبک و مقایسه دو Snapshot، خروجی @@CPU_BUSY میتواند کیفیت گزارش مدیریتی را بالا ببرد. ارزش تجاری زمانی ایجاد میشود که این داده به هشدار، ظرفیتسنجی یا کاهش زمان عیبیابی متصل شود.
استفاده از @@CPU_BUSY در پروژههای بزرگ چه مزیتی دارد؟
در پروژه بزرگ، استانداردسازی نحوه استفاده از @@CPU_BUSY باعث میشود تیم توسعه، DBA و پشتیبانی یک تعریف مشترک از CPU ticks و cumulative counter داشته باشند. این هماهنگی خطاهای تفسیر و دوبارهکاری را کاهش میدهد.
تفاوت @@CPU_BUSY با گزینه نزدیک آن چیست؟
@@CPU_BUSY دید کلی Instance میدهد؛ DMVها و Extended Events برای نسبت دادن CPU به Query دقیقترند. انتخاب صحیح باید بر اساس حجم داده، نیاز به خروجی Set-based و سطح جزئیات گزارش انجام شود؛ یک تابع scalar همیشه جایگزین کاتالوگویو یا DMV کامل نیست.
برای طراحی اسکریپت حرفهای مبتنی بر @@CPU_BUSY چه خدماتی لازم میشود؟
در پروژههای حساس میتوان منطق @@CPU_BUSY را در قالب رویه مانیتورینگ، Dashboard، گزارش زمانبندیشده یا کنترل Deployment پیاده کرد. تحلیل نیاز، تست روی نسخه واقعی SQL Server و مستندسازی خروجی، بخشهای مهم خدمات مشاوره و انجام پروژه هستند.
رایجترین خطا هنگام کار با @@CPU_BUSY چیست؟
یکی از خطاهای مهم این است که مقدار تجمعی است و باید Delta محاسبه شود. همچنین نادیده گرفتن NULL یا Context اجرای Query میتواند نتیجهای ظاهراً معتبر ولی از نظر عملیاتی اشتباه تولید کند.
آیا فراخوانی زیاد @@CPU_BUSY بر Performance اثر میگذارد؟
یک فراخوانی منفرد معمولاً سبک است، اما اجرای @@CPU_BUSY روی مجموعه بسیار بزرگ یا در شرطی که برای هر ردیف محاسبه شود میتواند هزینه ایجاد کند. ابتدا ردیفها را محدود کنید و در گزارشهای وسیع، جایگزین Set-based را ارزیابی کنید.
بهترین روش استفاده از @@CPU_BUSY چیست؟
بهترین روش این است که ورودی @@CPU_BUSY اعتبارسنجی، نوع خروجی صریح، حالت NULL مدیریت و نتیجه همراه زمان و Context ثبت شود. همچنین باید مشخص باشد که خروجی برای نمایش، کنترل ایمنی یا تصمیم کارایی مصرف میشود.
@@CPU_BUSY با کدام نسخههای SQL Server سازگار است؟
قابلیت قدیمی SQL Server است و بیشتر برای سازگاری و سنجش ساده استفاده میشود. با این حال، هنگام انتقال اسکریپت به Azure SQL یا Edition دیگر، Propertyها، مجوزهای Metadata و تفاوتهای پلتفرم را روی همان محیط آزمایش کنید.
سؤالات مصاحبه درباره @@CPU_BUSY
در مصاحبه چگونه تفاوت ورودی و خروجی @@CPU_BUSY را توضیح میدهید؟
پاسخ مناسب باید Syntax یعنی @@CPU_BUSY، نوع خروجی و شرایط NULL را توضیح دهد و یک نمونه از Baseline سبک ارائه کند.
چه زمانی بهجای @@CPU_BUSY از کاتالوگویو یا DMV استفاده میکنید؟
وقتی گزارش چندین ردیف و چند Property نیاز دارد، روش Set-based معمولاً مناسبتر است؛ @@CPU_BUSY برای تبدیل یا بررسی هدفمند یک مقدار بسیار خواناست.
چگونه نتیجه نامعتبر @@CPU_BUSY را از مقدار false یا صفر جدا میکنید؟
با بررسی صریح IS NULL، اعتبارسنجی ورودی و در صورت نیاز Join با Metadata منبع، علت نتیجه را روشن میکنم. این توضیح بهطور اختصاصی به @@CPU_BUSY مربوط است.
چه نکته Performance درباره @@CPU_BUSY مهم است؟
فراخوانی را پس از محدود کردن مجموعه داده انجام میدهم و از محاسبه تکراری @@CPU_BUSY در SELECT و WHERE جلوگیری میکنم.
یک سناریوی واقعی برای @@CPU_BUSY بیان کنید.
سناریوی مناسب میتواند هشدار فعالیت غیرعادی باشد؛ در آن خروجی همراه Timestamp، نام Database و شناسه نشست ثبت میشود تا قابل پیگیری باشد.
چکلیست نهایی استفاده از @@CPU_BUSY
- Syntax @@CPU_BUSY و ورودیهای آن با نسخه هدف تطبیق داده شده است.
- Context پایگاه داده یا Instance برای @@CPU_BUSY روشن است.
- مجوز لازم برای Metadata یا DMV بررسی شده است. در مبحث @@CPU_BUSY
- NULL، مقدار نامعتبر و حالت مرزی @@CPU_BUSY تست شده است.
- نمونه خروجی با نوع داده واقعی مقایسه شده است. در مبحث @@CPU_BUSY
- در Query بزرگ، هزینه فراخوانی تکراری @@CPU_BUSY اندازهگیری شده است.
- جایگزین Set-based برای گزارش انبوه ارزیابی شده است. در مبحث @@CPU_BUSY
- نتیجه نهایی همراه Timestamp و توضیح عملیاتی ثبت میشود. در مبحث @@CPU_BUSY
جمعبندی آموزش @@CPU_BUSY
@@CPU_BUSY ابزاری کوچک اما مؤثر برای با نمونهبرداری دورهای و محاسبه اختلاف میتوان روند کلی فعالیت CPU موتور را سنجید، هرچند برای تحلیل دقیق Query کافی نیست. است. استفاده حرفهای از آن به اعتبارسنجی ورودی، تفسیر نوع خروجی، کنترل NULL و انتخاب Scope مناسب وابسته است.
پس از تسلط بر @@CPU_BUSY، برای مقایسه آن با سایر ابزارهای این مجموعه به مقاله مادر توابع کمکی Performance و Metadata در SQL Server بازگردید.
خدمات برنامهنویسی و پایگاه داده
برنامهنویسی در اصفهان
قبول سفارشهای برنامهنویسی و پایگاه داده: 09131253620
انجام پروژههای برنامهنویسی، آموزش برنامهنویسی و آموزش پایگاه داده SQL Server با رویکرد حرفهای، مستند و قابل توسعه انجام میشود.
مجموعهای معتبر با سابقه فعالیت حرفهای از سال ۱۳۷۵ شمسی
از سال ۱۳۷۵ شمسی تاکنون در زمینه طراحی و اجرای پروژههای برنامهنویسی، پایگاه داده، سیستمهای تحت وب، وبسایت و راهکارهای نرمافزاری فعالیت میکنیم.
برای سفارش پروژههای برنامهنویسی و پایگاه داده، سیستمهای تحت وب، وبسایت و راهکارهای نرمافزاری جدید، با شماره تلفن همراه 09131253620 تماس حاصل فرمایید.
ایتا، واتساپ و تماس مستقیم: +989131253620
تماس با ما