AngularJS #2
Install-Package angularjs
<!DOCTYPE html> <html ng-app> <head> <title>Sample 1</title> </head> <body> <div ng-controller="GreetingController"> <p>{{greeting.text}}, World!</p> </div> <script src="../Scripts/angular.js"></script> <script> function GreetingController($scope) { $scope.greeting = { text: "Hello" }; } </script> </body> </html>
شاخصهای مهم بررسی کارآیی کوئریها
در ابتدای بررسی هر کوئری، باید 4 شاخص بسیار مهم، مدنظر باشند:
- مدت زمان اجرای کوئری: هرچند بررسی مدت زمان اجرای کوئری، شاخص مهمیاست، اما الزاما حاوی اطلاعات مفیدی در مورد آن کوئری نیست. برای مثال اگر یک کوئری زیاد طول میکشد، حتما به معنای وجود مشکلی با آن نیست؛ ممکن است اطلاعات زیادی را واکشی میکند یا ممکن است توسط عاملی سد شدهاست. در این موارد هرچند مشکلاتی وجود دارند، اما مستقیما مرتبط با آن کوئری نیستند.
- میزان مصرف CPU: میزان کاری که باید توسط CPU انجام شود تا کوئری به نتیجه برسد.
- I/O: در SQL Server میتوان هم physical I/O و هم logical I/O را بررسی کرد. برای مثال اگر اطلاعات مورد درخواست توسط کوئری هم اکنون در حافظه موجود باشند، نیازی به physical I/O پرهزینه نخواهد بود و در مقابل آن logical I/O کم هزینهتر است.
- میزان مصرف حافظه
در کل هر کدام از این شاخصها اگر دارای مقدار بالایی باشند، بیانگر وجود مشکلی است.
مروری بر ابزارهای مختلف اندازهگیری شاخصهای کارآیی
Management studio
درون Management studio میتوان اطلاعات مرتبط با یک کوئری را به صورت زنده مشاهده کرد. البته این اطلاعات صرفا مرتبط با یک کوئری و یا تعدادی مشخص هستند؛ چون باید کوئری را به صورت دستی درون این برنامه اجرا کرد و سپس اطلاعات اجرای کوئریها را دریافت نمود. اطلاعات آماری که توسط آن نیز ارائه میشود محدودیتهایی دارد. برای مثال مدت زمان اجرای کوئری و یا تعداد رکوردهای تحت تاثیر قرار گرفته شده را میتوان مشاهده کرد. اما به اندازهی اطلاعات ارائه شدهی در یک execution plan کامل نیست. به علاوه بازگشت اطلاعات حاصل از اجرای کوئریها درون این برنامه، سربار خودش را داشته و سبب کند شدن برنامه میشود. در آخر اطلاعات ارائه شدهی توسط آنرا نیز باید از قسمتهای مختلفی جمع آوری و به صورت دستی ذخیره کرد.
Extended Events
توسط Extended Events نیز میتوان همانند Management studio، اطلاعات آماری یک تک کوئری و یا یک batch را جمع آوری کرد؛ اما پس از ایجاد و تنظیم آن، به صورت خودکار اجرا میشود. در حین تعریف یک سشن Extended Events میتوان شاخصهای خاصی را انتخاب کرد و یا شرطهای دقیقی را اعمال کرد. خروجی آن نیز به صورت خودکار در یک فایل ذخیره میشود.
Dynamic management objects
با استفاده از DMO's از نتایج آماری مرتبط با تک کوئریها، به نتایج تجمعی حاصل از اجرای آنها میرسیم. این نتایج نیز در plan cache ذخیره میشوند. به این معنا که اگر کش، تخلیه (با اجرای دستور DBCC FREEPROCCACHE) و یا سرور ریاستارت شود، این اطلاعات از دست خواهند رفت. هدف آن بیشتر رفع اشکال کوئریهایی است که هم اکنون در حال اجرا هستند. اگر نیاز به اطلاعات دورهای را داشته باشید، نیاز خواهید داشت تا با تهیهی snapshotهایی از بانک اطلاعاتی، این تاریخچه را تکمیل کنید. به همین جهت Query Store ارائه شدهاست تا نیازی به اینکار نباشد.
Query Store
Query Store کار ذخیره سازی متن plan و آمار تجمعی مرتبط با آنرا به صورت خودکار انجام میدهد و آنرا درون بانک اطلاعاتی کاربر ذخیره میکند. به همین جهت با خالی شدن کش، برخلاف DMO's، اطلاعات آن حذف نمیشود.
مثالی از روشهای مختلف جمع آوری اطلاعات آماری حاصل از اجرای کوئریها در SQL Server
در ادامه قصد داریم با مثالی، خلاصهای را از سه قسمتی که تاکنون بررسی کردیم، ارائه دهیم. برای این منظور ابتدا رویهی ذخیره شدهی زیر را ایجاد میکنیم:
USE [WideWorldImporters]; GO DROP PROCEDURE IF EXISTS [Application].[usp_GetPersonInfo]; GO CREATE PROCEDURE [Application].[usp_GetPersonInfo] (@PersonID INT) AS SELECT [p].[FullName], [p].[EmailAddress], [c].[FormalName] FROM [Application].[People] [p] LEFT OUTER JOIN [Application].[Countries] [c] ON [p].[PersonID] = [c].[LastEditedBy] WHERE [p].[PersonID] = @PersonID; GO
سپس یک سشن Extended event را با نام QueryPerf ایجاد میکنیم:
IF EXISTS ( SELECT * FROM sys.server_event_sessions WHERE [name] = 'QueryPerf') BEGIN DROP EVENT SESSION [QueryPerf] ON SERVER; END GO CREATE EVENT SESSION [QueryPerf] ON SERVER ADD EVENT sqlserver.sp_statement_completed( WHERE ([duration]>(1000))), ADD EVENT sqlserver.sql_statement_completed( WHERE ([duration]>(1000))), ADD EVENT sqlserver.query_post_execution_showplan ADD TARGET package0.event_file( SET filename=N'C:\Temp\QueryPerf\test.xel',max_file_size=(256)) WITH ( MAX_MEMORY=16384 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS, MAX_DISPATCH_LATENCY=5 SECONDS,MAX_EVENT_SIZE=0 KB, MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF); GO
در ادامه Query Store را نیز بر روی بانک اطلاعاتی WideWorldImporters فعال کرده و همچنین اگر اطلاعاتی از پیش در آن وجود دارند، پاک میشود.
USE [master]; GO ALTER DATABASE [WideWorldImporters] SET QUERY_STORE = ON; GO ALTER DATABASE [WideWorldImporters] SET QUERY_STORE ( OPERATION_MODE = READ_WRITE, CLEANUP_POLICY = (STALE_QUERY_THRESHOLD_DAYS = 30), DATA_FLUSH_INTERVAL_SECONDS = 60, INTERVAL_LENGTH_MINUTES = 5, MAX_STORAGE_SIZE_MB = 100, QUERY_CAPTURE_MODE = ALL, SIZE_BASED_CLEANUP_MODE = AUTO, MAX_PLANS_PER_QUERY = 200); GO ALTER DATABASE [WideWorldImporters] SET QUERY_STORE CLEAR; GO
سپس هر آنچه را که در plan cache نیز وجود دارد، حذف میکنیم:
DBCC FREEPROCCACHE; GO
اکنون سشن QueryPerf را که پیشتر ایجاد کردیم، آغاز میکنیم:
ALTER EVENT SESSION [QueryPerf] ON SERVER STATE = START; GO
در ادامه چون میخواهیم نتایج آماری را در management studio نیز مشاهده کنیم، ابتدا جمع آوری شاخصهای آماری را در یک پنجرهی جدید new query، فعال میکنیم:
SET STATISTICS IO ON; GO SET STATISTICS TIME ON; GO SET STATISTICS XML ON; GO
همچنین در منوی Query، گزینهی Include client statistics را نیز انتخاب میکنیم تا مشخص شود که آیا عملیات insert/update/delete انجام شدهاست. چه تعداد ردیف تحت تاثیر اجرای این کوئری قرار گرفتهاند. چه تعداد تراکنش انجام شدهاست. همچنین اطلاعات آماری شبکه و زمان نیز ارائه شوند.
پس از این تنظیمات، اکنون نوبت به اجرای کوئریهای زیر رسیدهاست که یکی پارامتری است و دیگری AdHoc:
USE [WideWorldImporters]; GO EXECUTE [Application].[usp_GetPersonInfo] 1234; GO SELECT [s].[StateProvinceName], [s].[SalesTerritory], [s].[LatestRecordedPopulation], [s].[StateProvinceCode] FROM [Application].[Countries] [c] JOIN [Application].[StateProvinces] [s] ON [s].[CountryID] = [c].[CountryID] WHERE [c].[CountryName] = 'United States'; GO
سپس سشن QueryPerf را متوقف و حذف میکنیم:
ALTER EVENT SESSION [QueryPerf] ON SERVER STATE = STOP; GO DROP EVENT SESSION [QueryPerf] ON SERVER; GO
اگر بخواهیم از عملیات صورت گرفته توسط DMO's کوئری بگیریم:
SELECT [qs].[last_execution_time], [qs].[execution_count], [qs].[total_elapsed_time], [qs].[total_elapsed_time]/[qs].[execution_count] [AvgDuration], [qs].[total_logical_reads], [qs].[total_logical_reads]/[qs].[execution_count] [AvgLogicalReads], [t].[text], [p].[query_plan] FROM sys.dm_exec_query_stats [qs] CROSS APPLY sys.dm_exec_sql_text([qs].sql_handle) [t] CROSS APPLY sys.dm_exec_query_plan([qs].[plan_handle]) [p] WHERE [t].[text] LIKE '%Countries%'; GO
همانطور که مشاهده میکنید، شاخصهای چهارگانهای که در ابتدای بحث معرفی شدند، در مورد کوئری پارامتری نوشته شده، وضعیت بسیار بهتری نسبت به کوئری AdHoc دوم دارند.
از Query Store هم میتوان به صورت زیر کوئری گرفت (علاوه بر قسمت رابط کاربری Query Store که ذیل اشیاء مرتبط با بانک اطلاعاتی WideWorldImporters در management studio قابل مشاهدهاست):
USE [WideWorldImporters]; GO SELECT [qsq].[query_id], [qst].[query_sql_text], CASE WHEN [qsq].[object_id] = 0 THEN N'Ad-hoc' ELSE OBJECT_NAME([qsq].[object_id]) END AS [ObjectName], [qsp].[plan_id], [rs].[count_executions], [rs].[avg_logical_io_reads], [rs].[avg_duration], TRY_CONVERT(XML, [qsp].[query_plan]), [rs].[last_execution_time], (DATEADD(MINUTE, -(DATEDIFF(MINUTE, GETDATE(), GETUTCDATE())), [rs].[last_execution_time])) AS [LocalLastExecutionTime] FROM [sys].[query_store_query] [qsq] JOIN [sys].[query_store_query_text] [qst] ON [qsq].[query_text_id] = [qst].[query_text_id] JOIN [sys].[query_store_plan] [qsp] ON [qsq].[query_id] = [qsp].[query_id] JOIN [sys].[query_store_runtime_stats] [rs] ON [qsp].[plan_id] = [rs].[plan_id] WHERE [qst].[query_sql_text] LIKE '%Countries%'; GO
چک لیست تهیه یک برنامه ASP.NET MVC
- در گزارشات ... «بهتر» است اعمال شود. مثلا با کم کردن تعداد فیلدها به تعدادی که نمایش داده میشوند، میتوان مصرف حافظه برنامه را کاهش داد. شاید یک جدول شما 20 خاصیت داشته باشد و در یک گزارش فقط 5 مورد آن نمایش داده شود. 15 مورد دیگر صرفا مصرف کننده حافظه خواهند شد اگر از viewModel استفاده نکنید. (ولی ... در کل بهتر است اینگونه باشد)
نظرتون راجع به UpdatePanelچیه؟میشه ازش استفاده کرد در اون زمینه ای که بالا پرسیدم؟یعنی کل قسمتی که عکس داره رو بندازیم تو یه اپدیت پنل و وقتی کاملا لود شد ازش استفاده کنیم.آیا با کدهای جاوا تداخل ایجاد نمیکنه؟
ممنون
AngularJS #1
راه اندازی StimulSoft Report در ASP.NET MVC
http://localhost:14425/tableproduct/printtable?reporttype=21
/tableproduct/PrintTable?reporttype=21&mvcviewer_resource=scripts&mvcviewer_id=MVCViewer1&mvcviewer_theme=Office2013&mvcviewer_loc= fi9Db250ZW50L1N0aW11bHNvZnQvTG9jYWxpemF0aW9uL2ZhLnhtbA%3d%3d&mvcviewer_version=2015.2
مقابله با XSS ؛ یکبار برای همیشه!
Employee ID: {Orders.EmployeeID} --- GLine: {GroupLine}
در فرم ظاهر شده مقادیر را به صورت زیر وارد نمایید:
Name: TotalPrice Alias: TotalPrice Type: decimal Value: Order_Details.UnitPrice * Order_Details.Quantity
ایجاد گزارش به صورت Master-Detail:
برای ایجاد چنین گزارشی نیاز به ارتباط بین جدولها میباشد. با توجه به نحوه ایجاد Connection برای این مثال، روابط بین جدولها انتقال داده نشده است ولی شما میتوانید رابطه بین جدولها را اضافه نمایید حتی اگر این رابطه در منبع اطلاعات وجود نداشته باشد. برای این مثال نیاز به دو رابطه بین جدول Orders Detail و جدولهای Orders, Products میباشد. برای انجام این کار کافیست در پنل Dictionary بر روی جدول Orders Detail رایت کلیک کنید و گزینه New Relation را انتخاب نماید. همانند تصاویر زیر مقادیر را ست نمایید.
حال بر روی صفحه طراحی بعد از بند DataBand1 به ترتیب بندهای Header و Data و Footer را اضافه نمایید. در بند HeaderBand2 چهار کامپوننت Text قرار دهید و به ترتیب از سمت چپ مقادیر زیر را در خصوصیت Text کامپوننتها قرار دهید.
ProductName UnitPrice Quantity TotalPrice
{Order_Details.Products.ProductName} {Order_Details.UnitPrice} {Order_Details.Quantity} {Order_Details.TotalPrice}
{Sum(DataBand2,Order_Details.TotalPrice)}
حال میتوانید خروجی گزارش Master-Detail را از سربرگ Preview مشاهده نمایید. در صورتی که همانند تصویر بالا گزارش را طراحی کرده باشید در خروجی گزارش فاصلهای بین سطرها ایجاد شده است که علت آن ارتفاع کمتر کامپوننتهای Text نسبت به بندهای خود میباشد. برای رفع این مشکل، شما سه راه حل دارید.
الف: یکسان سازی ارتفاع کاپوننتها با بند دربرگیرنده آنها
ب: ست کردن خصوصیت Can Shrink بند دربرگیرنده کامپوننتها به مقدار true
ج: ست کردن خصوصیت Grow to Height کامپوننتهای Text به مقدار true
در این مثال ما از روش دوم استفاده میکنیم و خصوصیت Can Shrink بندهای HeaderBand2 و DataBand2 را به مقدار true ست میکنیم.
کامپوننتهای Panel و Clone :
Panel: به شما امکان میدهد تا کامپوننتها و بندها را دربر بگیرد و در واقع گروهی از کامپوننتها را ایجاد خواهد کرد. پنل میتواند مستقل بر روی صفحه طراحی قرار گیرد و یا در یک بند.
Clone: به شما امکان کپی کردن یک بخش از گزارش را میدهد که البته آن بخش فقط میتواند از نوع Panel باشد.
این دو کامپوننت یکی از عوامل قدرت این گزارشساز میباشد. برای شروع یک Page (صفحه طراحی) دیگر به گزارش اضافه کنید. میتوانید با رایت کلیک بر روی نوار سربرگهای محیط طراحی گزینه New Page را انتخاب نمایید. بر روی Page2 یک کامپوننت Panel قرار دهید، سپس از پنل Dictionary جدول Countries را دراگ کرده و در Panel1 رها کنید. در فرم Data تمامی فیلدها و بند Header را انتخاب نمایید، سپس یک کامپوننت Clone به صفحه طراحی اضافه کنید بلافاصله فرم Select Container ظاهر میشود، Panel1 را انتخاب کنید. حال شما میتوانید خروجی گزارش را مشاهده کنید، خروجی Page2 بعد از خروجی Page1 ظاهر خواهد شد.