بخشی از مقاله
حافظة اصلي پايگاه داده ها
Main Memory Database
مقدمه
در اواسط دهه 1980، با نزول قيمت DRAM، اين ايده مطرح شد که کامپيوترهاي آتي با داشتن حافظه اصلي با ظرفيت بالا، مي توانند بسياري از پايگاه داده ها را درحافظه اصلي داشته باشند. در اين شرايط مي توان همه I/O ها (که بسيار هزينه بر مي باشند) را از پردازش DBMS حذف نمود. بنابراين معماري DBMS دستخوش تغييرات جدي مي شود و در يک MAIN MEMORY DBMS(MMDBMS)، مديريت I/O ديگر نقشي نخواهد داشت.
نکته مهم در يک MMDB، چگونگي انجام تراکنشها و recovery بصورت کارا است. برخي از الگوريتمهاي پيشنهادي براساس اين فرض عمل مي کنند که قسمت کوچکي از حافظه اصلي بصورت ماندگار وجود دارد که اطلاعاتش توسط باطري در صورت قطع برق از بين نخواهد رفت. اين قسمت از حافظه اصلي براي نگهداري redo log ها استفاده مي شود.
تعداد ديگري از الگوريتمهاي پيشنهادي پيش فرض حافظه ماندگار را ندارند و همچنان از عمليات I/O براي نوشتن اطلاعات تراکنش در حافظه ماندگار استفاده مي کنند. بنابراين در اين الگوريتمها عمليات I/O بطور کامل حذف نمي شود، بلکه تعدادشان بسيار کمتر مي شود زيرا I/Oمربوط به نوشتن اطلاعات صفحات buffer ها، حذف خواهد شد.
در يک MMDBMS، ساختارداده هاي ساده مانند T-Tree و همچنين bucket-chained hash جايگزين ساختارداده هايي چون B-Tree و linear hash در DBMS هاي مبتني بر ديسک مي شوند. بنابراين سرعت اجراي پرس و جو(پرس و جو) و بهنگام سازي بسيار افزايش مي يابد و هزينه index lookup و نگهداري ،فقط مربوط به پردازنده و دسترسي به حافظه اصلي خواهد شد.
يکي از مشکلات اصلي در MMDBMS ها بهينه کردن درخواستهاست. عدم وجود I/O به عنوان فاکتور اصلي در هزينه ها به معناي پيچيدگي بيشتر مدل کردن هزينه در يک MMDBMS است زيرا در اينجا يکسري فاکتورهاي فازي از قبيل هزينه اجراي پردازنده ، بايد در نظر گرفته شوند. در اين حالت بايد با استفاده از تعامل روش coding، عوامل سخت افزاري مانند پردازنده و معماري حافظه و پارامترهاي پرس و جو، به يک مدل قابل اطمينان از هزينه اجرا در حافظه اصلي رسيد.
در دهه 1990، MMDBMS ها با افزايش سايز ديسکها و سايز مسائل همراه با افزايش ظرفيت DRAM ها، به اوج محبوبيت خود رسيدند. MMDBMS ها اغلب براي برنامه هايي که به پايگاه داده Real Time نياز دارند (مانند سيستمهاي embedded سوئيجهاي تلفن) ، استفاده مي شود. از آنجايط که سايز حافظه اصلي در کامپيوترها روز به روز در حال افزايش است، اين اميد وجود دارد که براي بسياري از پايگاه داده هايي که امروزه امکان قرارگفتن آنها بصورت کامل در حافظه اصلي وجود ندارد، اين شرايط مهيا شود.
مدلهاي هزينه حافظه اصلي
متاسفانه تا کنون تلاشهاي اندکي جهت مدل کردن هزينه کارايي MMDBMSها صورت گرفته است. تحقيقات اوليه روي طراحي ماشينهاي پايگاه داده ها، بيشتر در زمينه وابستگيهاي ميان الگوريتمها و دسترسي حافظه صورت مي گرفت.در صورتيکه امروزه به دليل محدود شدن استفاده از MMDBMS ها به کاربرد در پايگاه داده هاي Real Time(به صورت پرس وجوهاي ساده، مانند يک hash lookup در يک جدول)، اينگونه تحقيقات از اهميت کمتري برخوردارند.
در تحقيقات اخير در زمينه MMDBMS ها دو نمونه تحقيقاتي Office-By-Example (OBE) مربوط به شرکت IBM و Smallbase مربوط به شرکت HP مسائل ارزشمندي را درمورد بهينه سازي پرس وجو ها و مدلسازي هزينه حافظه اصلي مطرح کرده اند که در ادامه به بررسي اين دو نمونه مي پردازيم.
Office-By-Example (OBE)
OBE يک پايگاه داده در حافظه اصلي است که بسياري از مفاهيمQuery-by-example(QBE)، را گسترش مي دهد. براي بهينه سازي پرس و جو، مبتني بر هزينه، OBE يک مدل کامل از هزينه را ارائه مي دهد. باتوجه به اين پيش فرض که داده هايي که پردازش مي شوند در حافظه اصلي قرار گرفته اند، عامل اصلي هزينه در پايگاه داده هاي متداول که همان دسترسي I/O است حذف خواهد شد.
در اين صورت هزينه محاسبات پردازنده از اهميت بالايي برخوردار خواهد شد. اين در حاليست که مدلسازي هزينه پردازنده بسياردشوار است و پارامترهاي زيادي از قبيل طراحي نرم افزار، معماري سخت افزار و حتي روش برنامه نويسي، در مدلسازي هزينه پردازنده دخيل هستند. بعلاوه تحليل دقيق سيستمهاي بزرگ به منظور شمارش تعداد سيکلهاي پردازنده غير ممکن مي باشد.
راه حل پيشنهادي، استفاده از روشهاي تجربي و روشهاي تحليلي در کنار يکديگر است.
در ابتدا، bottleneck هاي سيستم با استفاده از يک تحليلگرِ اجرا شناسايي مي شوند. در اين روش تنها bottleneck ها، براي مدلسازي هزينه پردازنده بکار مي روند.
البته در اين مرحله، بسيار مهم است که bottleneck ها تا حد ممکن توسط تلاشهاي معقول اصلاح شوند.
مرحله بعد پيدا کردن وزن نسبي هريک از bottleneck ها و مشخص سازي واحد هزينه آنها توسط روشهاي تجربي است.
براي OBE، bottleneck ها و واحدهاي هزينه بصورت زير مشخص مي شوند :
• ارزيابي expression هايي که در predicate ها آمده اند. (واحد هزينه = C1)
• عمليات قياسي که براي مشخص کردن خروجي نهايي predicate ها لازم است. (واحد هزينه = C2)
• بازيابي يک tuple از يک رابطه موجود در حافظه اصلي. (واحد هزينه = C3)
• واحد عملياتِ ساختن شاخص (index) ( ساختن شاخص روي رابطه اي که n تا tuple دارد، nLog2n برابر واحد هزينه دارد. واحد هزينه = C4)
• واحد عمليات در مرتب سازي ،که در شرايط شاخصهاي چند ستوني(multi-column index) مورد نياز است. (واحد هزينه = C5)
جالبترين نتيجه بدست آمده از آزمايشات اين است که، هزينه ارزيابي expression هاي سيستم، بيشترين هزينه از ميان هزينه هاي مطرح شده در OBE مي باشد.در حاليکه C2 تا C5 تقريبا يکسان مي باشند، C1 به ميزان قابل توجهي بيشتر از آنهامي باشد.
در ادامه به بررسي نمونه Smallbase مي پردازيم.
Smallbase
در smallbase، مدل هزينه حافظه اصلي به سه گروه تقسيم مي شود:
1. Hardware-based
اين مدل بسيار شبيه مدل هزينه مبتني بر I/O در پايگاه داده هاي متداول است. به جاي شمارش عمليات I/O، تعداد سيکلهاي پردازنده شمارش مي شود. عليرغم اينکه اين روش بسيار ساده به نظر مي رسد، از جهت پياده سازي مشکلات عمده اي وجود دارد.بعلاوه، portability بسيار محدود خواهد شد زيرا اين سياستها ميان معماريهاي سخت افزار، متفاوت است. در هر حال اين مدل بسيار دقيق و قابل لطمينان مي باشد.
2. Application-based
در اين روش هزينه ها بر اساس هزينه bottleneck هاي سيستم بيان مي شود.عليرغم اينکه اين روش از جهت پياده سازي بسيار ساده تر از روش hardware-based است، اين نوع مدل از عموميت کمتري برخوردار است.
Bottleneck ها بسيار وابسته به workload ِمورد استفاده براي شناسايي آنها، دارد و بنابراين نمي توان از اين روش براي نمايش هزينه هاي همه انواع پرس و جو استفاده کرد.
در اصل،اين مدل نسبت به مدل hardware-based از portability بالاتري (توسط توليد دوباره پروفيل) برخوردار است. به هر حال، اين روش نه تنها باعث تفاوت در واحدهاي هزينه مي شود بلکه مجموعه bottleneck ها هم متفاوت خواهد شد.در اين حالت اگر مدل، دستخوش تغييرات شود، هزينه توابعِ هزينه مربوط به عمليات پايگاه داده، بايد دوباره بر اساس bottleneck هاي جديد فرمولسازي شود.
3. Engine-based
اين مدل هزينه، مابين مدل hardware-based - که دقيق و پيچيده است- و مدل application-based -که عليرغم سادگي از عموميت کمتري برخوردار است-، قرار دارد. اين مدل بر اساس هزينه عمليات ابتدايي که موتور اجرايي MMDBMS تامين مي کند، عمل مي کند.
در يک پروسه دو مرحله اي اين مدل توضيح داده مي شود:
در اين مدل عمومي ابتدا عوامل اصلي هزينه شناخته مي شوند و هزينه پردازش پرس و جو بر اساس عوامل شناخته شده بيان مي گردد. سپس مدل با مشخص کردن مقادير مربوط به اين عوامل، مقداردهي اوليه شده و سپس ارزيابي مي شود.
مرحله اول نياز به اطلاعات کامل در مورد اجزاي داخلي موتور اجرايي دارد و عموماً توسط دست انجام مي شود. در مورد اينکه مدل تا چه حد بايد جزئي و دقيق باشد، اين پاسخ مطرح مي شود که مدل بايد تا آنجايي که به feasibility سيستم خدشه اي وارد نشود، بصورت جزئي مدل شود. يکسري ساده سازيها و بهبود و دوباره نگري در طي مرحله ارزيابي قابل انجام است.
براي سيستم smallbase ، هزينه هاي ابتدايي زيرشناسايي شده اند :
• Fetch کردن يک ستون ويا مقدار يک پارامتر
• انجام عمليات رياضي و منطقي
• اجراي يک عمل مقايسه
• اجراي expression ايي که like داشته باشد
• scan کردن جدول، T-tree index، hash index، جدول موقت
• ساخت و از بين بردن T-tree index، hash index، جدول موقت
• مرتب سازي tuple ها
• انتخاب tuple هاي مشخص
• انجام عمل join (nested loop join، merge join)
به وابستگيهاي هزينه به فاکتورهايي از قبيل سايز جداول، نوع داده ها و ... در مرحله دوم پرداخته مي شود.
در مرحله دوم يک برنامه تست ،وظيفه مقداردهي اوليه و ارزيابي مدل را بصورت اتوماتيک برعهده دارد. براي هر واحد هزينه دو پرس و جو که هزينه اجرايشان، فقط در آن مقدار متفاوت باشد، در نظر گرفته مي شود. بعلاوه فرمولهايي که وابستگي هر واحد هزينه را به سايز جدولها نشان مي دهند، بايد مشخص شوند.
برنامه تست هزينه سپس پارامترهاي مربوطه و ارزيابي مدل را با اجراي هر زوج پرس و جو به تعداد مکرر با سايزهاي متفاوت جداول انجام مي دهد.
ساختارهاي شاخص در حافظه اصلي
ساختارهاي شاخصِ طراحي شده براي حافظه اصلي، متفاوت از طراحي هاي رايج براي سيتم هاي مبتني بر ديسک مي باشند.اهداف اصلي در طراحي يک شاخص مبتني برديسک عبارتند از : به حداقل رساندن تعداد دستيابي ها به ديسک و به حداقل رساندن فضاي ديسک.در حالي که يک شاخص مبتني بر حافظه اصلي ،در حافظه اصلي قرار گرفته واصلا دستيابي به ديسک وجود ندارد که حداقل شود از اين رو، هدف اصلي از طراحي يک ساختار شاخص مبتني بر حافظه اصلي ،کاهش زمان کلي محاسبات و در عين حال ، به کار گيري حداقل حافظه ممکن مي باشد.
در يک پايگاه داده مبتني بر حافظه اصلي، رابطه ها در حافظه قرار مي گيرند،بنابراين،نيازي نخواهد بود که شاخص، مقادير واقي صفات را ذخيره کند، در عوض مي توان از اشاره گر هايي به tupleها استقاده نمود و با استفاده از اين اشاره گرها ، مقادير واقعي صفات را در هنگام لازم ، بازيابي نمود.
چنين روشي جندين مزيت دارد:
با استقاده از اشاره گرِ tuple،شاخص، هم به مقادير صفات آن tuple دسترسي دارد و هم به خود tuple ،بنابراين اندازه شاخص کاهش مي يابد.
اين روش ، سبب کاهش پيچيدگي در سازماندهيِ رکوردهايي با اندازه هاي زياد و متغير،و روشهاي فشرده سازي در شاخص ها مي شود.
با انجام عمليات بهنگام سازي،شاخص ها نيز بايد بهنگام شوند، در اين حالت، جابجايي اشاره گرها بسيار ارزان تر از جابحايي مقادير صقاتِ (معمولاً) طولاني تر مي باشد.
يک اشاره گر شاخص، امکان دستيابي به کليه فيلدهاي يک tuple را فراهم مي سازد،بنابراين در حالتهاي خاص نيز، نياز کمتري به شاخص هاي چندصفتي، وجود خواهد داشت.
ساختار T-Tree ، يک ساختار درختي با حفظ ترتيب مي باشد که اساساً به منظور استفاده در حافظه اصلي طراحي شده است و در ادامه به شرح آن مي پردازيم.
ساختار T-Tree
اين ساختار جديد، از ترکيب ساختارهاي AVL و B-Tree بدست آمده است: T-Tree يک درخت باينري است با چندين عنصر در هر گره.در شکل زير، ساختار يک T-Tree و يک گره از آن را – به نام T-Node- مشاهده مي کنيد. T-Treeيک درخت باينري است بنابراين خصوصيت Binary Search را از درختان AVL، به طور ذاتي به همراه دارد.همچنين، هر T-Node شامل چندين عنصر مي باشد بنابراين T-Tree ، خصوصيات مثبتِ بهنگام سازي و ذخيره سازي B-Tree را به همراه دارد.جابجايي داده ها که عموماً پس از حذف و درج لازم مي شود نيز، معمولا تنها در يک گره بايد صورت بگيرد.Rebalancing نيز با استفاده از چرخشهايي مشابه با درختهاي AVL ، انجام مي شود با اين تفاوت که با توجه به امکان جابحايي داده در داخل يک گره، تناوب انجام آن خيلي کمتر خواهد بود.
سه گونه متفاوت از T-Node ها وجود دارند:
Internal Node: (گره داخلي):T-Node ايي که دو زير درخت دارد.
Half-leaf node : T-Node ايي که يک اشاره گرِ فرزند تهي و يک اشاره گرِ فرزند غير تهي دارد.
Leaf Node :T-Node ايي که هر دو اشاره گرِ فرزند آن، تهي مي باشند.
به ازاي هر گره داخليA، يک leaf (و يا half-leaf ) متناظر با آن وجود دارد که شامل مفدار داده ايي است که ،"جد "(predecessor) ِ کمترين مقدار داده در A ، محسوب مي شود.همچنين، يک leaf (ويا half-leaf) ،شامل مفدار داده ايي که ،successor ِ بيشترين مقدار داده در A ، محسوب مي شود،نيز وجودخواهد داشت.به predecessor، بزرگترين حد پائين A و به successor کوچکترين حد بالاي A ، گفته مي شود،مطابق با شکل زير:
به ازاي هر گره N و هر مفدار X ، اگر مقدار X مابين مقاديرکمترين عنصر و بيشترين عنصردرA ، قرار بگيرد، مي گوئيم که A ، X را "مي پوشاند". توجه کنيد که داده ها در يک T-Node به صورت مرتب شده قرار مي گيرند، بنابراين،سمت چپ ترين عنصر داراي کوچکترين مقدار و سمت راست ترين عنصر ، داراي بزرگترين مقدار خواهند بود.
هر T-Tree داراي يک حدِ حداقل و يک حدِ حداکثر مي باشد که معمولا به ميزان اندکي با هم تفاوت دارند، گره هاي داخلي ظرفيتشان - يعني : تعداد مقاديرداده در هر گره - را در داخل بازه اين حدود،نگه مي دارند، بدين ترتيب در تلفيقي از عمليات حدف و درج،مقدار داده ايي که بايد به علت سربارحاصل از درج به leafها منتقل شده و يا به علت پاريز (underflow) حاصل ازحذف ،از leafها قرض گرفته شود،کاهش يافته و نتيجتاً از چرخشهاي اضافي در درخت، جلوگيري خواهد شد. داشتن چنين انعطافي در ظرفيت گره هاي داخلي، تا حدودي سبب حفظ تعادل ميان بهبود ِ ذخيره سازي و زمانِ حذف/درج خواهد شد. گره هاي leaf و half-leaf نيز،ظرفيتي متغير ميان صفرو حد ِحداکثر خواهند داشت.
1. الگوريتم جستجو
جستجو در T-Tree مانند جستجو در Binary Tree صورت مي گيرد با اين تفاوت که به جاي مقايسه با يک مقدار،مانند B-Tree، مقايسه با مقادير حداقل وحداکثرِ آن گره صورت مي گيرد.مراحل اين الگوريتم عبارتند از:
1. جستجو هميشه از ريشه درخت آغاز مي شود.
2. اگر مقدار مورد جستجو کمتر از کمترين مقدار در آن گره باشد،جستجو در زير درختي ادامه خواهد يافت که اشاره گرِ فرزند چپ، به آن اشاره مي کند.
3. در غير اين صورت، اگر مقدار مورد جستجو، بيشتر ازبزرگترين مقدار در آن گره باشد،جستجو در زير درختي ادامه خواهد يافت که اشاره گرِ فرزند راست،به آن اشاره مي کند.
4. در غير اين صورت، گره فعلي جستجو خواهد شد.
5. جستجو هنگامي نا موفق خواهد بود که گره ايي جستجو شود ولي داده مورد نظر در آن يافت نشود و يا هنگامي که گره ايي که مقدار ِمورد جستجو را بپوشاند، پيدا نشود.
2 . الگوريتم درج
عمليات درج با جستجو براي گره پوشاننده ،آغاز مي شود، مفدار جديد در اين گره درج شده و سپس درخت به منظور Rebalancing بررسي مي شود.اگر توازن درخت در اثر درج (و يا حذف)، به هم خورده باشد، پروسه Rebalancing ِ مناسب، گرههايي که در مسير ريشه تا leaf آيي که در آن حذف/ درج صورت گرفته است، را بررسي خواهد کرد. مراحل اين الگوريتم عبارتند از:
1. جستجو براي يافتن گره پوشاننده
2. اگر چنين گره ايي پيدا شد و براي اضافه کردن آيتم جديد، جا داشت، مقدار جديد به اين گره اضافه شده و الگوريتم متوقف مي شود.در غير اين صورت،کمترين عنصر از گره بر داشته شده و مقداري که بايد درج شود ، به آن اضافه شده و به عنوان کمترين عنصرقرار داده مي شود.سپس به سراغ leafي که بزرگترين حدِ پائين را براي گره در بر گيرنده عنصر درج شونده، دارا مي باشد، رفته و آن کمترين عنصر را که از گره پوشا برداشته بوديم ، به آن اضافه مي کنيم،که از اين پس به عنوان بزرگترين حد پائين براي گره پوشا، محسوب خواهد شد.
3. اگر در جستجوي درخت، چنين گره ايي پيدا نشد، مقدار درج شونده، به آخرين گره در مسير جسنجو- که يا leaf است و يا half-leaf - اضافه خواهد شد،اگر در آن جا شود که به عنوان عنصر حداقل/حداکثر جديد براي آن گره محسوب خواهد شد،در غير اين صورت،leaf جديدي ساخته و عنصر درج شونده به عنوان اولين عنصر ِ آن، به آن اضافه خواهد شد.
4. اگر leaf جديدي به درخت اضافه شود، توارن درخت بايد مورد بررسي قرار بگيرد بدين نحو که: در مسير جستجو از leaf تا ريشه، هر گره بررسي شده و اگر تفاوت عمقِ دو زير درخت آن، بيش از يک سطح بود، بايد چرخش صورت بگيرد.با انجام يک چرخش، توازن درخت تصحيح شده و عمليات متوقف مي شود.
در اينجا ذکر اين نکته ضروري است که ، هنگامي که يک گره داخلي سرريز مي کند و در نتيجه، عنصر حداقل آن برداشته شده و به يک leaf منتقل مي شود، اين درج در leaf ، منجر به جابجايي هيچ گونه داده نخواهد شد چرا که مقدار جديد به عنوان سمت راست ترين آيتم، در leaf قرار خواهد گرفت در حالي که اگر مي بايست، عنصر حداکثر برداشته شود، در leaf به عنوان سمت چپ ترين آيتم وارد شده و در نتيجه جابجايي داده در داخل گره (leaf) ، بايد صورت بگيرد.به همين دليل،با برداشتن عنصر حداقل به جاي عنصر حداکثراز گره ، از اين جابجايي جلوگيري خواهد شد.
3. الگوريتم حذف
الگوريتم حذف مشابه الگوريتم درج مي باشد، بدين ترتيب که: عنصري که بايد حذف شود، جستجو شده،عمليات انجام مي شود و در صورت نياز Rebalancing صورت مي گيرد. مراحل اين الگوريتم عبارتند از:
1. گره پو شاننده ِ مقدار حذف شونده، جستجو شده، مقداري که بايدحذف شود در داخل اين گره، جستجو شده و در صورت عدم وجود اين مقدار، اعلام خطا شده و الگوريتم متوقف مي شود.
2. اگر عمل حذف منجر به پاريز نشود( يعني: اگر گره تا پيش از حذف،بيش از کمترين مفدار مجاز،داده دارد) ، عنصري که بايد حذف شود را حذف کرده و الگوريتم متوقف مي شود.در غير اين صورت، اگر گره پوشاننده يک گره داخلي است، عنصر حذف شونده را حذف کرده و به منظور رساندن تعداد عناصر گره به حداقل مجاز، برزگترين حد پايين را براي آن از يک leaf و ياhalf-leaf ، قرض مي گيريم.در غير اين صورت( گره پوشاننده يا leaf است و يا half-leaf)،تنها عنصر حذف شونده را حذف مي کنيم( leafها مجاز به پاريز هستند ودر گام 3 ، بهhalf-leaf ها مي پردازيم)
3. اگر گره ، يک half-leafاست و ميتواند در يک leaf ، ادغام شود،دو گره را به يکي (leaf) تبديل کرده و آن يکي گره را پاک مي کنيم.ادامه در گام 5
4. اگر گره جاري(leaf)، خالي است ؛ آن را آزاد کرده و به گام 5 مي رويم به منظور Rebalancing ِ درخت.در غير اين صورت،الگوريتم متوقف مي شود.
5. در مسيرِ از leaf تا ريشه، هر گره بررسي شده و اگر تفاوت ارتقاعِ دو زير درخت آن، بيش از يک بود، بايد چرخش صورت بگيرد، از آن جايي که چرخش در يک گره، ممکن است موجب ايجاد عدم توارن در گره ايي در مکاني بالاتر در درخت شود،بررسي توازن در عمل حذف، بايد بر روي تمام گره ها در مسير جستجو صورت بگيرد، تا جايي که گره ايي با توازنِ برابر، يافت شود.
کنترل همزماني( Concurrency Control)
دسترسي به حافظه اصلي بسيار سريعتر از دسترسي به ديسک مي باشد، بنابراين مي توان انتظار داشت که در يک سيستم حافظه اصلي ، تراکنشها بسيار زودتر انجام شوند.در سيستمهايي که از روشهاي کنترل همزماني، مبتني بر lock ، بهره مي برند،اين بدين معنا مي باشد که lock ها مدت زمان زيادي نگه داشته نخواهند شد و بنابراين، تداخل در lock ها به اندازه وقتي که داده ها بر روي ديسک قرار دارند؛ اهميت نخواهد داشت.به همين دليل در سيستمهايي که از پيمانه هاي (granules)کوچک ِ داده (مانند field ها يا record ها ) به منظور کاهش تداخل استفاده مي کنند،در صورتي که داده ها در حافظه اصلي قرار گرفته باشند، فلسفه اصلي اين کار از بين رفته و پيشنهاد مي شود که در چنين حالتي از پيمانه هاي خيلي بزرگ (مانند relation ها ) استفاده شود.
در سيستمهاي locking متداول، lock ها از طريق يک hash table پياده سازي مي شوند که اطلاعات مربوط به آيتم هايي را دارا مي باشد که در حال حاضر lock شده اند و خود داده ها (بر روي ديسک) ، هيچ گونه اطلاعاتي در مورد lock را در بر ندارند.اگر داده ها در حافظه اصلي قرار گرفته باشند، مي توان با اضافه کردن چند بيت به آنها، وضيعت ِ lock شان را نيز ذخيره نمود، بدين ترتيب که : اگر اولين بيت سِت شده باشد، آن داده lock شده و در غير اين صورت، آزاد است.اگر
داده، lock شده و دومين بيت نيز سِت شده است، بدين معنا مي باشد که دو يا بيشتر تراکنش ِ منتظر نيز وجود دارند.شناسه اين تراکنشهاي منتظر نيز در يک hash lock table معمولي ذخيره خواهند شد.اگر تراکنشي بخواهد که داده ايي را lock کند، ابتدا وضعيت lock bit آن را بررسي مي کند و اگر سِت نشده بود، آن را سِت کرده و فرايند locking تمام مي شود.اگر داده قبلاً lock شده بود نيز،دومين بيت را سِت کرده و خودش را به ليست تراکنشهاي منتظر در lock table اضافه مي کند.هنگامي که تراکنش اوليه lock اش را آزاد مي کند،بررسي مي کند که آيا دومين بيت سِت شده است يا خير،اگر سِت نشده بود که کار تمام است و در غير اين صورت نيز بايد روال معمول به منظور صدا زدنِ يکي از تراکنشهاي منتظر، طي شود.
Commit Processing
براي جلوگيري ازfailure هايي که ممکن است در سيستم پيش بيايند، لازم است که يک نسخه پشتيبان(backup) و يک log از فعاليتهاي تراکنشها داشته باشيم و از آن جائيکه حافظه اصلي معمولاvolatile است، اين log بايد در يک حافظه ماندگار قرار بگيرد.
پيش از آن که تراکنشي بتواند commit کند، بايد فعاليت هايش در log درج شده باشند.عمليات log کردن مي تواند بر روي " زمان پاسخ" (response time) تاثير بگذارد، زيرا هر تراکنش ،قبل از commit شدن، بايد حداقل براي يک write ِ ماندگار، منتظر بماند.همچنين در صورتي که log به bottleneck تبديل شود،عمليات log کردن ممکن است برروي کارايي نيز تاثير بگذارد.اگر چه اين مشکلات در سيستمهاي مبتني بر ديسک نيز وجود دارند، ولي در سيستمهاي حافظه اصلي ، جدي تر مي باشند زيرا که در اين حالت،log کردن تنها عمليات مبتني بر ديسکي است که يک تراکنش لازم دارد.براي حل اين مشکل، چندين راه حل پيشنهاد شده است به شرح زير:
مي توان از بخش کوچکي از حافظه ماندگار استفاده نمود به منظور نگه داري قسمتي از log .پروسه و يا پردازنده خاصي نيز مسوؤل کپي کردن داده ها از حافظه ماندگار به روي ديسکهاي log خواهد بود.اگر چه اين روش ، مشکل bottleneck شدن ِ log را برطرف نخواهد کرد ولي با حذف زمان انتظار تراکنشها براي عمليات مبتني بر ديسک ،سبب از بين رفتن مشکل " زمان پاسخ" خواهد شد.
در صورتي که حافظه ماندگار در دسترس نباشد، تراکنشها مي توانند از روش Pre-committing استفاده نمايند،بدين ترتيب که به محض آن که فعاليتهاي تراکنش در log ثبت شد، مي تواند lock هايش را آزاد کند، بدون آنکه منتظر بماند تا اين اطلاعات به ديسک منتقل شوند.
براي حل مشکل bottleneck شدن ِ log مي توان از روش Group Committing استفاده نمود، در اين روش،اطلاعات log يک تراکنش ، به محض آن که commit کرد، به ديسک log فرستاده نمي شوند،بلکه با جمع شدن تعداد زيادي از log ها (مثلاً به اندازه يک page) ،همگي با هم در يک عمل، به روي ديسک منتقل مي شوند،بدين ترتيب در هر عمليات ،چندين تراکنش commit شده و تعداد کل عمليات لازم، کاهش مي يابد.
روشهاي دستيابي(Access Methods)
تعداد زيادي ساختار شاخص، مختص پايگاه داده هاي مقيم در حافظه اصلي ، طراحي و ارزيابي شده اند که از آن جمله، مي توان به انواع گوناگون hashing و درختها اشاره نمود.hashing در جستجو و بهنگام سازيِ سريع مفيد است ، ولي به اندازه ساختارهاي درختي در فضا، صرفه جويي نکرده و همچنين، از پرس و جو هاي بازه اي (range query) نيز، پشتيباني نمي کند.
يک نکته کلي در کليه روشهاي دستيابي در حافظه اصلي، اين مي باشد که نيازي به ذخيره سازي مقادير داده – که شاخصها بر روي آن ها ساخته مي شوند- در خود شاخص نمي باشد.توجه کنيد که دسترسي تصادفي در حافظه اصلي سريع بوده و اشاره گرها به آساني دنبال مي شوند، به همين دليل،ساختارهاي شاخص مي توانند به جاي مقادير داده ايي، اشاره گرهايي را به آنها ذخيره کنند،بدين ترتيب مشکل ذخيره سازي فيلدهايي با طول متغير در شاخص، حل شده و چون اشاره گرها کوچکتر از داده هايي هستند که به آنها اشاره مي کنند ، در ميزان حافظه مصرفي نيز به مقدار قابل توجهي، صرفه جويي مي شود.
نمايش داده ها (Data Representation )
از روش فوق ، همچنين مي توان به نحو مطلوبي در نمايش داده ها استفاده کرد، بدين ترتيب که : tupleهاي رابطه مي توانند به عنوان يک مجموعه از اشاره گر ها به مقادير ِ داده ايي، ارائه شوند.استفاده از اشاره گر،هنگامي که مقادير بزرگ چندين بار در پايگاه داده تکرار مي شوند، به صرفه مي باشد چرا که مقدار واقعي داده، تنها يکبار ذخيره خواهد شد.همچنين، اشاره گرها، مشکل فيلدهايي با طول متغير را با استفاده از اشاره گرهايي به يک Heap ، راحت تر کنترل خواهند کرد.