i ++ – Telegram
80 subscribers
55 photos
15 videos
17 files
61 links
Yourself ++
Download Telegram
#string_interning
#dotnet
#C#


Interned strings have the following characteristics:

Two interned strings that are identical will have the same address in memory.
Memory occupied by interned strings is not freed until your application terminates.
Interning a string involves calculating a hash and looking it up in a dictionary which consumes CPU cycles.
If multiple threads intern strings at the same time they will block each other because accesses to the dictionary of interned strings are serialized.
The consequences of these characteristics are:

You can test two interned strings for equality by just comparing the address pointer which is a lot faster than comparing each character in the string. This is especially true if the strings are very long and start with the same characters. You can compare interned strings with the Object.ReferenceEquals method, but it is safer to use the string == operator because it checks to see if the strings are interned first.

If you use the same string many times in your application, your application will only store one copy of the string in memory reducing the memory required to run your application.

If you intern many different strings this will allocate memory for those strings that will never be freed, and your application will consume ever increasing amounts of memory.

If you have a very large number of interned strings, string interning can become slow, and threads will block each other when accessing the interned string dictionary.

You should use string interning only if:

The set of strings you are interning is fairly small.
You compare these strings many times for each time that you intern them.
You really care about minute performance optimizations.
You don't have many threads aggressively interning strings.
#NAT
#network

NAT Table
#web
#server_side
#client_side

In summary, client-side routing is a technique for handling web application navigation and page rendering in the browser using JavaScript frameworks, while server-side routing is a technique for handling navigation and rendering on the server using server-side technologies.

Client-side and server-side routing are two different approaches to handling web application navigation and page rendering:

Client-side routing is a technique where the browser renders the pages and handles navigation without requiring a full page refresh. This is achieved using JavaScript frameworks like React, Angular, or Vue.js. In client-side routing, the browser makes AJAX requests to the server to fetch data, and then the JavaScript framework dynamically updates the content on the page. This approach provides a seamless user experience, as it avoids the delay and flicker associated with full page reloads.

Server-side routing, on the other hand, is a technique where the server is responsible for rendering the pages and handling navigation. This is achieved using server-side technologies like PHP, Ruby on Rails, or Django. In server-side routing, the server generates HTML pages and sends them to the browser for rendering. This approach is more suitable for applications that require strong SEO (Search Engine Optimization) or that need to support older browsers that may not have full support for client-side JavaScript.
#iis
#web


This is a configuration file for Microsoft Internet Information Services (IIS) that sets up URL rewriting rules for a web application built with React.
The <rewrite> section of the configuration file is used to define URL rewriting rules that modify incoming requests to the web server.

The <rules> section contains a single rule with the name "React Routes". This rule matches all incoming requests (<match url=".*" />) and has three conditions:

<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />: This condition checks if the requested file is not a physical file on the server.

<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />: This condition checks if the requested file is not a directory on the server.

<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />: This condition checks if the requested URL does not start with "/api", which is used for API requests.

If all three conditions are met, the request is rewritten to the root URL (<action type="Rewrite" url="/" />). This is useful for React applications that use client-side routing, where all requests are initially directed to the root URL and the React app handles routing based on the URL path.

<?xml version="1.0"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="React Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
#clean_code
#dependency_inversion
#SOLID

The Dependency Inversion Principle (DIP)
The Dependency Inversion Principle (DIP) states that a high-level class must not depend upon a lower-level class. They must both depend upon abstractions. And secondly, an abstraction must not depend upon details, but the details must depend upon abstractions.

// Not following the Dependency Inversion Principle
public class SalaryCalculator
{
public float CalculateSalary(int hoursWorked, float hourlyRate) => hoursWorked * hourlyRate;
}
public class EmployeeDetails
{
public int HoursWorked { get; set; }
public int HourlyRate { get; set; }
public float GetSalary()
{
var salaryCalculator = new SalaryCalculator();
return salaryCalculator.CalculateSalary(HoursWorked, HourlyRate);
}
}


These classes do not follow the “Dependency Inversion Principle” as the higher-level class EmployeeDetails is directly dependent upon the lower-level SalaryCalculator class.
We can fix this issue as below.

// Following the Dependency Inversion Principle
public interface ISalaryCalculator
{
float CalculateSalary(int hoursWorked, float hourlyRate);
}
public class SalaryCalculatorModified : ISalaryCalculator
{
public float CalculateSalary(int hoursWorked, float hourlyRate) => hoursWorked * hourlyRate;
}
public class EmployeeDetailsModified
{
private readonly ISalaryCalculator _salaryCalculator;

public int HoursWorked { get; set; }
public int HourlyRate { get; set; }
public EmployeeDetailsModified(ISalaryCalculator salaryCalculator)
{
_salaryCalculator = salaryCalculator;
}
public float GetSalary()
{
return _salaryCalculator.CalculateSalary(HoursWorked, HourlyRate);
}
}


Benefits of Dependency Inversion Principle in C#:

1. Flexibility: With abstractions in place, swapping implementations becomes seamless, enabling the integration of new modules without affecting existing code.

2. Modularity: Code is divided into smaller, manageable modules, making it easier to understand, maintain, and extend.

3. Testability: Abstractions facilitate easy mocking and unit testing, allowing developers to write robust test suites for their applications.

4. Reduced Coupling: Dependencies between modules are minimized, reducing the overall coupling and enhancing code stability.

Dependency Injection Techniques in C#

1. Constructor Injection: Injecting dependencies through the constructor of a class.
2. Property Injection: Injecting dependencies through public properties of a class.
3. Method Injection: Injecting dependencies as parameters of a method.
#معرفی_فیلم
#maze_runner

یه ملتی خیلی تعریف این فیلمو میدادن...امروز نشستیم دیدیم. خب هیجان و ایناش که بالا بود هیچی. ولی چون قرار شده بود فقط وقت گذروندن نباشه فیلم دیدنمون و دنبال هدف نویسنده باشیم، اندکی دربارش میخوام بحرفم.:)

از دید خیلی بالا بخوام بگم توی قسمت ۱ ش مشخص نشد اصلا هدف کل این همه بلا (که خودشون اسمش رو گذاشته بودن آزمایش:) ) یک سری انسان ها بر روی تعداد دیگه چیه و احتمالا باید توی قسمت‌های بعدیش مشخص بشه. اینو که ایگنور کنیم، میرسیم به چند عنصر که باعث نجات ملت اسیر شده شد.
اولیش قانون شکنی! فیلم کلا قانون رو یک سری چارچوب‌هایی دونسته که مردم بین خودشون برای انجامش به توافق میرسن و بعد از توافقش، دیگه حق ندارن ازش تخطی کنن و بشکننش وگرنه با مجازات روبرو میشن حتی اگر راه نجاتشون در رد کردن اون قانون‌ها باشه. در نهایت هم توی فیلم با شکستن همه قانون‌هایی که بینشون بود، تونستن از مخمصه نجات پیدا کنن. فکر میکنم تا مقدار زیادی درست باشه اگر قانون رو مثلا عرف امروز در نظر بگیریم،‌ لزومی نداره همه کارایی که میکنیم طبق عرف (حتی قانون) باشه.
دومیش رفاقته! این دوستان غربی هرچقدر هم که تونسته باشن مفاهیمی که برای ما پاکه رو به گند بکشن، این یکی رو فکر میکنم هنوز نتونسته و نمیتونن:) دوستی و رفاقت و ارزش‌هاش. یا حداقل توی فیلماشون که براش خیلی ارزش قائل میشن بر خلاف چیزای دیگه.
سومیش هم که تیپیکال این نوع فیلم‌ها هست، جنگیدن برای زنده موندن. این مفهوم شدیدا زیاده توی فیلما. درسته جذابیت فیلم رو میبره بالا ولی چه تاثیری میتونه توی مخاطب داشته باشه؟‌ اخه ۹۹ درصد مخاطبایی که توانایی دیدن این فیلما رو دارن، توی چنین شرایطی نیستن. پس چرا اینقد چنین شرایطی رو نشون میدن و یه جورایی نشون میدن که باید برا زندگی و ادامش، بجنگی، طاقت بیاری، زنده بمونی؟چرا؟
همین تقریبا:) ببینیم کی وقت بشه ۲ش رو ببینیم که ادامش رو بگم:)
خیلی موقع‌ها میخوایم یه بازه زمانی رو توی کدمون اندازه‌گیری کنیم که خب راه‌های زیادی براش هست و معروف‌ترینش هم timer یا timespan هست. ولی از dotnet 7 به بعد یه متد جدید برای StopWatch اومده که اورهد خیلی کمتری داره و توصیه میشه از اون استفاده بشه.

https://www.youtube.com/watch?v=NTz99yN2urc
Forwarded from مشورت کامپیوتری‌ها (Navid)
#database
#elasticsearch

برای ادامه تاک‌ها نیاز هست که یکم اطلاعاتمون رو درباره دیتابیس‌ها و فیچر‌هایی که هر کدوم در اختیارمون قرار میده، بالا ببریم. برای همین سعی میشه که توی چند تا پست و کامنت‌های پست‌ها، به معرفی و توضیح انواع دیتابیس‌ها بپردازیم. پس از دستشون ندین...😉


توی این پست میخوایم یه اشاره ای به elasticsearch بکنیم و یکسری قابلیت‌های اون رو بررسی و برای ادامه مسیر چند تا منبع معرفی کنیم.
اگه elasticsearch رو توی دسته دیتابیس‌ها قرار بدیم می‌تونیم بهش بگیم یه دیتابیس NoSql هست ولی معمولا از اون به عنوان یک search engine یاد می‌کنند و خب دلیلش هم اینه که مهارت اصلیش توی سرچ‌ کردن سریع و برگردوندن داده مورد نیاز در کمترین زمان ممکنه. از کاربردش بخوام بگم یه جورایی الان دیگه توی هر سایتی که یه سرچ‌ باکسی میبینین که داره روی تعداد زیادی دیتا سرچ میزنه و نتیجه رو باسرعت براتون میاره، به احتمال زیاد اون پشت داده‌ها رو داره از elasticsearch واکشی می‌کنه.
خب حالا به نظرتون لازمه اینکه elasticsearch بتونه جست‌وجوی سریع داشته باشه‌ چیه؟ آفرین. اینه که بتونه یه جوری داده رو ذخیره و ایندکس‌گذاری کنه که با اون نوع ذخیره سازی، با اون ساختمان داده، بتونه بالاترین سرعت واکشی داده رو داشته باشه. elasticsearch برای اینکار از Inverted Index استفاده می‌کنه که می‌تونین جزییاتش رو از این لینک بخونین. با همین روش‌ هست که elasticsearch سرعت جست‌وجوی خودش رو نزدیک به realtime معرفی می‌کنه و خب بیراه هم نیست!
یکی از ویژگی‌های elasticsearch مقیاس‌پذیری بالای اون و قابلیت horizontal scalability هست که باعث میشه از این ابزار توی داده‌ها با اسکیل بالا، به راحتی استفاده بشه و ...
برای آشنایی بیشتر می‌تونین این لینک‌ها رو مطالعه کنین:
لینک ۱
لینک ۲
#csharp
#dotnet
#delegate


Whenever we use delegates, we have to declare a delegate, initialize it, and then call a method with a reference variable.

In order to get rid of all the first steps, we can directly use Func, Action, or Predicate delegates.

- The Func delegate takes zero, one or more input parameters, and returns a value (with its out parameter).
- The action takes zero, one or more input parameters, but does not return anything.
- Predicate is a special kind of Func. It represents a method that contains a set of criteria mostly defined inside an if condition and checks whether the passed parameter meets those criteria or not. It takes one input parameter and returns a boolean - true or false.


//// Func Examples
//1
List<Func<int, int, int>> myActions = new List<Func<int, int, int>>();
myActions.Add(AddNumber);
int result = myActions.First()(10, 20);
Console.WriteLine($"result = {result}");
//2
Func<int, int, int> myAddition = (num1, num2) => num1 + num1;
Console.WriteLine($"result 2 = {myAddition(12, 13)}");
//3
Func<int, int, int> myAddition2 = delegate(int num1, int num2)
{
return num1 + num2;
};
Console.WriteLine($"result 3 = {myAddition2(14, 15)}");
//// Action Examples
//1
Action<int, int> myAction = Printer;
myAction(12, 13);
//2
Action<int, int> myAction2 = (a, b) => Console.WriteLine($"lambda: a = {a}, b = {b}");
myAction2(100, 2);
//3
Action<int, int> myAction3 = delegate(int a, int b)
{
Console.WriteLine($"delegate : a = {a} , b = {b}");
};
myAction3(100, 222);
//// Predicate
//1
Predicate<int> myPre = IsOdd;
Console.WriteLine($"myPre is : {myPre(123)}");
//2
Predicate<int> myPre2 = (a) => a % 2 == 1;
Console.WriteLine($"Lambda: myPre is : {myPre2(123)}");
//3
Predicate<int> myPre3 = delegate(int a)
{
return a % 2 == 1;
};
Console.WriteLine($"delegate: myPre is : {myPre3(123)}");
///////////////
///////////////
int AddNumber(int a, int b)
{
return a + b;
}
void Printer(int a, int b)
{
Console.WriteLine($"a = {a} , b = {b}");
}
bool IsOdd(int a)
{
return a % 2 == 1;
}
database-concepts.pdf
5.9 MB
رفرنس دارم چه رفرنسی:)
#oracle
#database
#sql
#proxmox
#linux
#network
#id


some DHCP servers are using client ID, not MAC address to assign IP addresses. You will need to reset the machine id before cloning. I used the commands below and it worked for me:

the option 61 is the "client-ID" or client identifier

Two main options are used in this case: the vendor class identifier (option 60) and the client identifier (option 61). Client identifier is unique and helps the DHCP server to manage its clients and leases, it is generally set to the MAC address of the network interface on a local network. The vendor class identifier is more interesting, as it identifies the vendor type and configuration of a DHCP client in a simple character string. The format is open and can be interpreted by the server in order to adjust the answer options and content.

ref

echo -n >/etc/machine-id
rm /var/lib/dbus/machine-id
ln -s /etc/machine-id /var/lib/dbus/machine-id



ورژن دستی کامندای بالا:))
uuidgen | tr -d - > /etc/machine-id
Forwarded from مشورت کامپیوتری‌ها (Navid)
#database
#sql
#oracle
#index


خب توی این پست می‌خوایم با چند تا از اصطلاح‌هایی که توی دیتابیس‌های sql ای به گوش می‌خوره مخصوصا indexها(با محوریت Oracle البته)، آشنا بشیم. از موارد ساده شروع میکنیم تا ...

توی دیتابیس‌های sql، ما یه table داریم که توی اون table تعدادی column با type مشخص ایجاد می‌شه که می‌تونیم داده‌هامون رو به صورت rowدر اون table ذخیره کنیم. این مقدمه ریز رو گفتم تا بتونیم بهتر index رو تعریف کنیم. index یه ساختمان داده آپشنال هست که اگه بخوایم، میشه روی یک یا چند ستون از جدولا تعریف کرد. ما وقتی روی یکسری ستون‌ها، index تعریف می‌کنیم، می‌تونیم با پرفورمنس بالایی، اون دیتا‌ها رو از دیتابیس واکشی کنیم. تعریف ‌index زمانی برای ما مفید می‌شه که برای یه کاربرد خاص، تعداد درخواست‌های نسبتا زیادی بر روی یکسری داده‌ها داریم، در این صورت می‌تونیم سرعت کل برنامه رو به کمک indexها افزایش بدیم.
نکته قابل توجهش اینه که تعریف index ها کاملا مستقل از داده اصلی هست و صرفا با استفاده از ساختمان‌داده مناسب، دسترسی به داده‌های index شده رو افزایش می‌ده. گفتم ساختمان‌داده‌های مناسب، بخوام یه اشاره‌ای بکنم، توی Oracle یکی از ساختمان داده‌‌هایی که برای این منظور استفاده میشه، B-Tree هست. (احتمالا جزو اون درختایی بوده که توی درس ساختمان‌داده خوندین و با خودتون گفتین خب به چه دردی می‌خوره🙂) همچنین متد‌های Reverse key indexes، Bitmap indexes و Function-based indexes هم در Oracle قابل استفاده هستند که برای مطالعه بیشتر می‌تونین به این لینک یه سر بزنین:)
یکی دیگه از دلایلی که استفاده از indexباعث افزایش سرعت واکشی میشه، اینه که باعث میشه دسترسی کمتری به بلوک‌های حافظه و I/O disk داشته‌باشه و این دسترسی رو به لطف همون ساختمان‌داده‌ها، به حداقل می‌رسونه.

در آخر هم درخواست ساختن index رو صرفا برای اینکه بفهمیم چقدر سادس(!) ببینیم:
CREATE INDEX index_name
ON table_name (column1, column2, ...columnN);


و در نهایت:)
برای اینکه اطلاعات بیشتر درباره index‌ها و نوع‌هاش و چگونگی کارکردش بدونین خوندن بخش Indexes and Index-Organized Tables از این داکیومنت که مال Oracle هست پیشنهاد میشه:)
#linux
#storage
#LVM


Logical Volume Manager (LVM)
Let’s start with LVM itself. The Logical Volume Manager is the software layer responsible for managing the logical volume infrastructure. It provides tools and utilities to create, resize, and manage logical volumes, volume groups, and physical volumes. LVM facilitates dynamic allocation and resizing of storage resources without requiring downtime.

Physical Volume (PV)
A physical volume refers to a physical storage device or LVM partition, such as a hard disk drive (HDD) or solid-state drive (SSD). LVM utilizes these physical volumes as building blocks for logical volume management.

Volume Group (VG)
A volume group is a collection of one or more physical volumes that are combined to form a single storage pool. It acts as a container for logical volumes and provides a higher level of abstraction for storage management. Within a volume group, available physical extents are pooled together.

Physical Extent (PE)
A physical extent is the smallest unit of allocation within a volume group. It represents a fixed-size block of storage space, typically a few megabytes in size, and is used for allocating logical volumes. The physical extents from different physical volumes are combined to form a single pool of available extents within a volume group.


Advantages of LVM:

Dynamic Storage Allocation
Logical Volume Snapshots
Striping and Mirroring
Volume Group Aggregation
Online Data Relocation
Backup and Restore Flexibility



pvcreate /dev/sdX
vgcreate myvg /dev/sdX

lvcreate -L 10G -n mylv myvg
#ParallelProcessing


متد های مختلف موازی سازی
Flynn classification:

SISD
SIMD
MISD
MIMD

Enslow:
#database
#partitioning
#oracle

بریم سراغ یکی از قابلیت‌های دیتابیس‌ها که تو حجم بالای داده، خیلی به دردمون می‌خوره. پارتیشنینگ. پارتیشنینگ میاد برامون جدول‌ها و ایندکس های خیلی بزرگ رو میشکنه به قسمت‌های کوچیک‌تر تا بتونیم مدیریت بهتری روشون داشته باشیم و کارایی رو ببریم بالا.
با یه مثال ادامه بدیم. فرض کنین مدیر یه کتابخونه هستین و تعداد زیاااادی کتاب زیر دستتون هست که باید با سرعت بالایی کتاب مورد نظرتون رو پیدا کنین و بدین به درخواست کننده. خب برای این کار یکی از راه‌هاش اینه که یه قفسه بزررررگ داشته باشین که همه کتاب‌ها توی اون قفسه باشه و هر بار که میخواین یه کتابی رو پیدا کنین از اول تا آخر بگردین که بتونین اون کتاب رو پیدا کنین و برش دارین. ولی خب همونطور که دیدین هیچ کتابدار عاقلی این حرکت رو نمیزنه!:) یکی از راه‌هایی که می‌تونیم این کار رو به صورت بهینه تر انجام بدیم و بهمون کمک می‌کنه که بتونیم مدیریت بهتری روی کتاب‌ها داشته باشیم، اینه که بیایم اون قفسه بزررررگ رو به قفسه‌های کوچک‌تری بشکنیم و توی هر قفسه یه سری کتاب خاص رو قرار بدیم که وقتی نیاز داشتیم به اون نوع کتاب‌های خاص بدونیم باید بریم سراغ کدوم قفسه. مثلا بیایم کتاب‌ها رو بر اساس سال چاپ بذاریم توی قفسه‌های مختلف. یا اینکه بر اساس موضوع بذاریم توی قفسه‌های مختلف یا ... . به این کار کتابدار توی دیتابیس میگن پارتیشنینگ. حالا همین چطوری جدا کردن این قفسه‌ها خودش می‌تونه روش‌های مختلفی داشته باشه که باعث می‌شه پارتیشنینگ‌های مختلفی داشته باشیم:
Range Partitioning
Interval Partitioning
List Partitioning
Hash Partitioning
Refrence Partitioning
Composite Partitioning

قبل از اینکه این موارد رو یه توضیح مختصری بدیم نیازه که با Partition Key آشنا بشیم. Partition Key یک یا مجموعه‌ای از ستون‌ها هست که با توجه به اون ها تصمیم گرفته میشه که یه ردیف از داده، توی کدوم پارتیشن قرار بگیره. هر ردیف داده، به صورت یکتا توی یک پارتیشن قرار میگیره.
خب بریم سراغ این انواع پارتیشن‌ها:
Range Partitioning:
توی این دسته، دیتابیس ردیف‌های داده رو بر اساس یه رنجی از مقدار Partitioning Key به پارتیشن‌ها میده که ذخیره کنند. این دسته معمولا بر اساس تاریخ و زمان هست. مثلا پارتیشنینگ بر اساس سال ایجاد اون سطر داده‌، انجام بشه و همه داده‌های سال ۲۰۲۰ توی یه پارتیشن و ۲۰۲۱ توی یه پارتیشن و ... باشه.
Interval Partitioning:
این مدل از پارتیشنینگ، یه اکستنشن از Range Partitioning هست که ما رو از مشخص کردن دقیق رنج پارتیشن‌ها معاف می‌کنه. یعنی نیاز نیست که حتما همه رینج‌هایی که نیاز داریم رو تعریف کنیم، بلکه با تعریف یکسری Range و یک Interval، در صورتی که داده مورد نظر، توی اون Range نبود، دیتابیس خودش بر اساس اون Interval، یک پارتیشن ایجاد می‌کنه و داده رو در اون قرار میده.

List Partitioning:
توی این دسته، برای هر پارتیشن، یک لیستی از مقادیر برای هر پارتیشن، مشخص میشه که بر اساس مقدار Partitioning Key داده‌ها، در اون پارتیشن قرار می‌گیره یا نه. مثلا می‌تونیم بگیم نوع محصولات خوراکی رو بریز توی یه پارتیشن و نوع محصول پوشیدنی رو بریز توی یه پارتیشن دیگه.
Hash Partitioning:
توی این دسته، دیتابیس به کمک یک تابع Hash داخلی، تصمیم میگیره که داده رو بین پارتیشن‌ها تقسیم کنه. تو این مورد ما نمی‌تونیم بگیم که کدوم داده‌ها رو توی کدوم پارتیشن‌ها ذخیره کن بلکه فقط میگیم که داده‌ها رو توی چند تا پارتیشن قرار بده. دیگه دیتابیس خودش میدونه و مقدار خروجی تابع Hashش.:)
Refrence Partitioning:
این روش Partitioning داره میگه که هر استراتژی‌ای که برای ذخیره جدول‌های parrent توی دیتابیس هست، توسط جدول‌های child هم برقرار باشه. مثلا فررض کنین یک جدول Student داشته باشیم و یک جدول Code که کد های دانشجو‌ها توش نگهداری میشه به این صورت که هر سطر داده در جدول Code یک Student_id به عنوان کلید خارجی داره و نشون‌دهنده این هست که هر کد مال کدوم دانشجو هست. در این صورت هر ردیف داده در جدول Code در همون پارتیشنی ذخیره میشه که داده متانظر Student_id ش ذخیره شده. این کار باعث میشه که پرفورمنس جوین بین جداول بالا بره.

Composite Partitioning:
این دسته، شامل ترکیبی از انواع پارتیشنینگ که تا حالا باهاشون آشنا شدیم، میشه. به این صورت که می‌تونیم بعد از تعریف یه Partitioning خاص برای جدول، برای هر پارتیشن یک Subpartition هم تعریف کنیم. مثلا متد Composite Hash-Range Partitioning می‌تونه Subpartitionهای خودش رو را با Hash Partitioning از پارتیشن‌های ایجاد شده توسط Range Partitioning، ایجاد کنه.

و در آخر برای ادامه بازم لینک و داکیومنت جذاب و قشنگ...:)
می‌تونین برای آشنایی بیشتر با این مبحث، این لینک رو مطالعه کنین.