ایندکسهای XML ایی
ایندکسهای XML ایی، ایندکسهای خاصی هستند که بر روی ستونهایی از نوع XML تعریف میشوند. هدف از تعریف آنها، بهینه سازی اعمال مبتنی بر XQuery، بر روی دادههای این نوع ستونها است. چهار نوع XML Index قابل تعریف هستند؛ اما primary xml index باید ابتدا ایجاد شود. در این حالت جدولی که دارای ستون XML ایی است نیز باید دارای یک clustered index باشد. هدف از primary XML indexها، ارائهی تخمینهای بهتری است به بهینه ساز کوئریها در SQL Server.
جزئیات primary XML indexها
زمانیکه یک primary xml index را ایجاد میکنیم، node table یاد شده در قسمت قبل را، بر روی سخت دیسک ذخیره خواهیم کرد (بجای هربار محاسبه در زمان اجرا). متادیتای این اطلاعات ذخیره شده را در جداول سیستمی sys.indexes و sys.columns میتوان مشاهده کرد. باید دقت داشت که تهیهی این ایندکسها، فضای قابل توجهی را از سخت دیسک به خود اختصاص خواهند داد؛ چیزی حدود 2 تا 5 برابر حجم اطلاعات اولیه. بدیهی است تهیهی این ایندکسها که نتیجهی تجزیهی اطلاعات XML ایی است، بر روی سرعت insert تاثیر خواهند گذاشت. Node table دارای ستونهایی مانند نام تگ، آدرس تگ، نوع داده آن، مسیر و امثال آن است.
زمانیکه یک Primary XML Index تعریف میشود، اگر به Query Plan حاصل دقت کنید، دیگر خبری از XML Readerها مانند قبل نخواهد بود. در اینجا Clustered index seek قابل مشاهدهاست.
ایجاد primary XML indexها
همان مثال قسمت قبل را که دو جدول از آن به نامهای xmlInvoice و xmlInvoice2 ایجاد کردیم، درنظر بگیرید. اینبار یک xmlInvoice3 را با همان ساختار و همان 6 رکوردی که معرفی شدند، ایجاد میکنیم. بنابراین برای آزمایش جاری، در مثال قبل، هرجایی xmlInvoice مشاهده میکنید، آنرا به xmlInvoice3 تغییر داده و مجددا جدول مربوطه و دادههای آنرا ایجاد کنید.
اکنون برای ایجاد primary XML index بر روی ستون invoice آن میتوان نوشت:
CREATE PRIMARY XML INDEX invoice_idx ON xmlInvoice3(invoice) SELECT * FROM sys.internal_tables
در ادامه علاقمند هستیم که بدانیم داخل آن چه چیزی ذخیره شدهاست:
SELECT * FROM sys.xml_index_nodes_325576198_256000
اگر به این جدول دقت کنید، 6 ردیف اطلاعات XML ایی، به حدود 100 ردیف اطلاعات ایندکس شده، تبدیل گردیدهاست. با استفاده از دستور ذیل میتوان حجم ایندکس تهیه شده را نیز مشاهده کرد:
sp_spaceused 'xmlInvoice3'
--DROP INDEX invoice_idx ON xmlInvoice3
تاثیر primary XML indexها بر روی سرعت اجرای کوئریها
همان 10 کوئری قسمت قبل را درنظر بگیرید. اینبار برای مقایسه میتوان به نحو ذیل عمل کرد:
SELECT * FROM xmlInvoice WHERE invoice.exist('/Invoice[@InvoiceId = "1003"]') = 1 SELECT * FROM xmlInvoice3 WHERE invoice.exist('/Invoice[@InvoiceId = "1003"]') = 1
چند نکته در این تصویر حائز اهمیت است:
- Query plan کوئری انجام شده بر روی جدول دارای primary XML index، مانند قسمت قبل، حاوی XML Readerها نیست.
- هزینهی انجام کوئری بر روی جدول دارای XML ایندکس نسبت به حالت بدون ایندکس، تقریبا نزدیک به صفر است. (بهبود کارآیی فوق العاده)
اگر کوئریهای دیگر را نیز با هم مقایسه کنید، تقریبا به نتیجهی کمتر از یک سوم تا یک چهارم حالت بدون ایندکس خواهید رسید.
همچنین اگر برای حالت دارای Schema collection نیز ایندکس ایجاد کنید، اینبار کوئری پلن آن اندکی (چند درصد) بهبود خواهد یافت ولی نه آنچنان.
ایندکسهای XMLایی ثانویه یا secondary XML indexes
سه نوع ایندکس XML ایی ثانویه نیز قابل تعریف هستند:
- VALUE : کار آن بهینه سازی کوئریهای content و wildcard است.
- PATH : بهینه سازی انتخابهای مبتنی بر XPath را انجام میدهد.
- Property: برای بهینه سازی انتخاب خواص و ویژگیها بکار میرود.
این ایندکسها یک سری non-clustered indexes بر روی node tables هستند. برای ایجاد سه نوع ایندکس یاد شده به نحو ذیل میتوان عمل کرد:
CREATE XML INDEX invoice_path_idx ON xmlInvoice3(invoice) USING XML INDEX invoice_idx FOR PATH
پس از ایجاد ایندکس ثانویه بر روی مسیرها، اگر اینبار کوئری دوم را اجرا کنیم، به Query Plan ذیل خواهیم رسید:
همانطور که مشاهده میکنید، نسبت به حالت primary index، وضعیت clustered index seek به index seek تغییر کردهاست و همچنین دقیقا مشخص است که از کدام ایندکس استفاده شدهاست.
در ادامه دو نوع ایندکس دیگر را نیز ایجاد میکنیم:
CREATE XML INDEX invoice_value_idx ON xmlInvoice3(invoice) USING XML INDEX invoice_idx FOR VALUE CREATE XML INDEX invoice_prop_idx ON xmlInvoice3(invoice) USING XML INDEX invoice_idx FOR PROPERTY
سؤال: اکنون پس از تعریف 4 ایندکس یاد شده، کوئری دوم از کدام ایندکس استفاده خواهد کرد؟
در اینجا مجددا کوئری دوم را اجرا کرده و به قسمت Query Plan آن دقت خواهیم کرد:
برای مشاهده دقیق نام ایندکس مورد استفاده، کرسر ماوس را بر روی index seek قرار میدهیم. در اینجا اگر به قسمت object گزارش ارائه شده دقت کنیم، نام invoice_value_idx یا همان value index ایجاد شده، قابل مشاهدهاست؛ به این معنا که در کوئری دوم، اهمیت مقادیر بیشتر است از اهمیت مسیرها.
کوئریهایی مانند کوئری ذیل از property index استفاده میکنند:
SELECT * FROM xmlInvoice3 WHERE invoice.exist('/Invoice//CustomerName[text() = "Vahid"]') = 1
SELECT * FROM xmlInvoice3 WHERE invoice.exist('/Invoice//CustomerName[. = "Vahid"]') = 1
خلاصه نکات بهبود کارآیی برنامههای مبتنی بر فیلدهای XML
- در حین استفاده از XPath، ذکر محور parent یا استفاده از .. (دو دات)، سبب ایجاد مراحل اضافهای در Query Plan میشوند. تا حد امکان از آن اجتناب کنید و یا از روشهایی مانند cross apply و xml.nodes برای مدیریت اینگونه موارد تو در تو استفاده نمائید.
- ordinals را به انتهای Path منتقل کنید (مانند ذکر [1] جهت مشخص سازی نودی خاص).
- از ذکر predicates در وسط یک Path اجتناب کنید.
- اگر اسناد شما fragment با چند root elements نیستند، بهتر است document بودن آنها را در حین ایجاد ستون XML مشخص کنید.
- xml.value را به xml.query ترجیح دهید.
- عملیات casting در XQuery سنگین بوده و استفاده از ایندکسها را غیرممکن میکند. در اینجا استفاده از اسکیما میتواند مفید باشد.
- نوشتن sub queryها بهتر هستند از چندین XQuery در یک عبارت SQL.
- در ترکیب اطلاعات رابطهای و XML، استفاده از متدهای xml.exist و sql:column نسبت به xml.value جهت استخراج و مقایسه اطلاعات، بهتر هستند.
- اگر قصد تهیه خروجی XML از جدولی رابطهای را دارید، روش select for xml کارآیی بهتری را نسبت به روش FLOWR دارد. روش FLOWR برای کار با اسناد XML موجود طراحی و بهینه شدهاست؛ اما روش select for xml در اصل برای کار با اطلاعات رابطهای بهینه سازی گردیدهاست.
اثبات قانون مشاهدهگر در برنامه نویسی
NativeScript یک فریمورک متن باز برای ساخت برنامههای نیتیو موبایل با جاوا اسکریپت است.
Ionic فریمورک مبتنی بر Angular، به صورت متن باز برای توسعه نرم افزار تلفن همراه بکار میرود که باعث میشود برنامههای نیتیو و پیشرفته وب با تکنولوژیهای بالا ساخته شود.
React Native یک فریمورک جاوا اسکریپت برای ساخت برنامههای تلفن همراه نیتیو است که از فریمورک React استفاده میکند.
انتخاب یکی از این 3 گزینه در دنیای صنعت رو به رشد امروز دشوار است.
EF Code First #7
- در مثال سایت MVC، رابطه دپارتمان و ادمین آن هم «one-to-zero-or-one» است. به این نحو هم تعریف شده
modelBuilder.Entity<Department>() .HasOptional(x => x.Administrator);
public int? InstructorID { get; set; }
- رابطه کلاسهای Instructor و OfficeAssignment مثال سایت MVC مانند مثال قسمت هفتم فوق است و متد WithRequired رو ذکر کرده.
MongoDB #2
معرفی #F
#F یک زبان برنامه نویسی تابع گرا است و گزینه ای بسیار مناسب برای حل مسایل کامپیوتری. اما استفاده از زبان برنامه نویسی تابعی محض برای نوشتن و تولید پروژههای نرم افزاری مناسب نمیباشد. به همین دلیل نیاز به استفاده از این زبانها در کنار سایر زبانهای شی گرا احساس میشود. #F یک زبان همه منظوره دات نت است که برای حالت اجرا به صورت همه منظوره استفاده میشود. برخی زبانهای تابع گرا دیگر نظیر Lisp و Haskel و OCaml (که #F بسیار نزدیک به این زبان میباشد) با دستورات زبان اجرای سفارشی کار میکنند و این مسئله باعث نبود زبان برنامه نویسی چند فعالیته میشود. شما میتوانید از برنامه نویسی توصیفی هم استفاده کنید و توابع را به راحتی با هم ترکیب کنید و یا روشهای شی گرایی و دستوری را در همان برنامه استفاده کنید.
تاریخچه
#F توسط دکتر دون سیم ابداع شد. در حال حاضر #F وابسته به تیمی کوچک ولی پیشرفته واقع در مرکز تحقیقات شرکت مایکروسافت میباشد. #Fمدل خود را از روی زبان برنامه نویسی OCAML انتخاب کرد و سپس با گسترش قابلیتهای فنی، خود را در دات نت گنجاند. #F در بسیاری از برنامههای بزرگ دنیای واقعی استفاده شده است که این خود نمایانگر آکادمیک نبودن محض این زبان است. با توجه به اینکه زبان تابع گرای دیگر به ندرت در دات نت توسعه پیدا کرده است #F به عنوان استاندارد در این مقوله در آمده است. زبان #F از نظر کیفیت و سازگار بودن با دات نت و VisualStudio بسیار وضعیت بهتری نسبت به رقبای خود دارد و این خود دلیلی دیگری است برای انتخاب این زبان.
استفاده در دات نت
#F کاملا از دات نت پشتیبانی میکند و این قابلیت را به برنامه نویسان میدهد که هر چیزی را که در سایر زبانهای دات نت استفاده میکنند در این زبان نیز قابل استفاده باشد. همچنین میتواند برای کد نویسی IL نیز استفاده شود.
#F به راحتی قابل اجرا در محیط لینوکس و مکینتاش نیز است.
استفاده کنندگان #F
#F در شرکت مایکرو سافت به شدت استفاده میشود. رالف هربریش که یکی از مدیران دوگانه گروه بازیهای مایکروسافت و از متخصصین آموزش ماشین است در این باره میگوید:
*اولین برنامه کاربردی برای انتقال 110 گیگا بایت از طریق 11000 فایل متنی در بیش از 300 دایرکتوری و وارد کردن آنها در دیتابیس بود. کل برنامه 90 خط بود و در کمتر از 18 ساعت توانست اطلاعات مربوطه را در SQL ذخیره کند. یعنی ده هزار خط برنامه متنی در هر ثانیه مورد پردازش قرار گرفت.همچنین توجه کنید که من برنامه را بهینه نکردم بلکه به صورت کاملا عادی نوشتم. این جواب بسیار قابل توجه بود زیرا من انتظار داشتم حداقل یک هفته زمان ببرد.
دومین برنامه، برنامه پردازش میلیونها Feekback مشتریان بود. ما روابط مدلی زیادی را توسعه دادیم و من این روابط را در #F قرار دادم و دادههای مربوط به SQL را در آن فراخوانی کردم و نتایج را در فایل داده ای MATLAB قرار دادم و کل پروژه در حد صد خط بود به همراه توضیحات. زمان اجرای پروژه برای دریافت خروجی ده دقیقه بود در حالی که همین کار را توسط برنامه #C قبلا توسعه داده بودیم که بیش از هزار خط بود و نزدیک به دو روز زمان میبرد.*
Derivative One که یک شرکت بزرگ در تولید نرم افزارهای شبیه ساز مالی است مدلهای مالی نرم افزارهای خود را در #F پیاده سازی کرده است.
چرا #F ؟
همیشه باید دلیلی برای انتخاب یک زبان باشد. در حال حاضر #F یکی از قدرتمندترین زبانهای برنامه نویسی است. در ذیل به چند تا از این دلایل اشاره خواهم کرد:
- #F یک زبان استنباطی است. برای مثال در هنگام تعریف متغیر و شناسه نیاز به ذکر نوع آن نیست. کامپایلر با توجه به مقدار اولیه تصمیم میگیرد که متغیر از چه نوعی است.
- بسیار راحت میتوان به کتابخانه قدرتمند دات نت دسترسی داشت و از آنها در پروژههای خود استفاده کنید.
- #F از انواع روشهای برنامه نویسی نظیر تابعی، موازی، شی گرا و دستوری پیشتیبانی میکند.
- برخلاف تصور بعضی افراد، در #F امکان تهیه و توسعه پروژههای وب و ویندوز و حتی WPF و Silverlight هم وجود دارد.
- نوع کدنویسی و syntax زبان #F به برنامه نویسان این اجازه را میدهد که الگوریتمهای پیچیده مورد نظر خود را بسیار راحتتر پیاده سازی کنند. به همین دلیل بعضی برنامه نویسان این زبان را با Paython مقایسه میکنند.
- #F به راحتی با زبان #C و VB تعامل دارد. یعنی میتونیم در طی روند تولید پروژه از قدرتهای هر سه زبان بهره بگیریم.
- طبق آمار گرفته شده از برنامه نویسان، #F به دلیل پشتیبانی از نوع داده ای قوی و مبحث Unit Measure، خطاها و Bugهای نرم افزار را کاهش میدهد.
- به دلیل پشتیبانی VS.Net از زبان #F و وجود ابزار قدرتمند برای توسعه نرم افزار به کمک این زبان (unitTesting و ابزارهای debuging و ..)این زبان تبدیل به قدرتهای دنیای برنامه نویسی شده است.
- #F یک زبان بسیار مناسب برای پیاده سازی الگوریتمهای data-mining است.
- #F از immutability در تعریف شناسهها پشتیبانی میکند.(در فصلهای مربوطه بحث خواهد شد)
- و.....
چرا #F نه ؟
#F هم مانند سایر زبان ها، علاوه بر قدرت بی همتای خود دارای معایبی نیز میباشد. (مواردی که در پایین ذکر میشود صرفا بر اساس تجربه است نه مستندات).
- نوع کدنویسی و syntax زبان #F برای برنامه نویسان دات بیگانه ( و البته کمی آزار دهنده) است. اما به مرور این مشکل، تبدیل به قدرت برای مانورهای مختلف در کد میشود.
- درست است که در #F امکان تعریف اینترفیس وجود دارد و یک کلاس میتواند اینترفیس مورد نظر را پیاده سازی کند ولی هنگام فراخوانی متدهای کلاس (اون هایی که مربوط به اینترفیس است) حتما باید instance کلاس مربوطه به اینترفیس cast شود و این کمی آزار دهنده است.(در فصل شی گرایی در این مورد شرح داده شده است).
- زبان #F در حال حاضر توسط VS.Net به صورت Visual پشتیبانی نمیشود.(امکاناتی نظیر drag drop کنترلها برای ساخت فرم و ....). البته برای حل این مشکل نیز افزونه هایی وجود دارد که در جای مناسب بحث خواهیم کرد.
آیا برای یادگیری #F نیاز به داشتن دانش در برنامه نویسی #C یا VBداریم؟
به طور قطع نه. نوع کد نویسی (نه مفاهیم)در #F کاملا متفاوت در #C است و این دو زبان از نظر کد نویسی شباهتشان در حد صفر است. برای یادگیری #F بیشتر نیاز به داشتن آگاهی اولیه در برنامه نویسی (آشنایی با تابع، حلقه تکرار، متغیر ها) و شی گرایی(مفاهیم کلاس، اینترفیس، خواص، متدها و...) دارید تا آشنایی با #C یا VB.
چگونه شروع کنیم؟
اولین گام برای یادگیری آشنایی با نحوه کد نویسی #F است. بدین منظور در طی فصول آموزش سعی بر این شده است از مثالهای بسیار زیاد برای درک بهتر مفاهیم استفاده کنم. تا جای ممکن برای اینکه تکرار مکررات نشود و شما خواننده عزیز به خاطر مطالب واضح و روشن خسته نشوید از تشریح مباحث واضح خودداری کردم و بیشتر به پیاده سازی مثال اکتفا نمودم.
که شما میتوانید در هر پوشه View مربوط به هر کنترل یک ViewImports_ اختصاصی داشته باشید
برای مثال :
مسیرهای زیر را در در پوشه Views در نظر بگیرید:
Views/_ViewImports با محتوای زیر : (موجود در ریشه پوشه Views )
@using Core1RtmTestResources .Web @using Core1RtmTestResources .DomainLayer.Models @using Microsoft.AspNetCore.Identity @using Microsoft.AspNetCore.Mvc.Localization @using Core1RtmTestResources .Web.ViewModels.AccountViewModels //1 Move to Views/Account/_viewImports @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
و Views/Account که در این مسیر ViewImports_ اختصاصی در نظر گرفته شده است که میتوان قطعه کد شماره 1 مشخص شده در کد بالا را به این فایل انتقال داد
@using Core1RtmTestResources .Web.ViewModels.AccountViewModels
وظیفه هر ViewImports_ مشخص میشود و بار از ViewImports_ موجود در ریشه Views کم شده و به اصطلاح کد تمیزتری خواهید داشت.
و اما طی بررسی هایی که انجام دادم هنوز نتونستم متغیر(های) سراسری در ViewImports_ موجود در مسیر Views/Account تعریف کنم که در Viewهای موجود در همین مسیر قابل دسترسی باشد. به قطعه کد زیر توجه فرمایید :
@using Core1RtmTestResources.Web.ViewModels.AccountViewModels @inject IHtmlLocalizerFactory HtmlLocalizerFactory @{ var localizer = HtmlLocalizerFactory.Create( baseName: "Controllers.TestLocalController" /*مشخصات کنترلر جاری*/, location: "Core1RtmTestResources.ExternalResources" /*نام اسمبلی ثالث*/); var sharedLocalizer = HtmlLocalizerFactory.Create( baseName: "SharedResource" /*مشخصات*/, location: "Core1RtmTestResources.ExternalResources" /*نام اسمبلی ثالث*/); }