همانطور که می دانیم، ستون های کلید مربوط به یک ایندکس در (SQL Server(Clustered Index or Non-Clustered Index دارای محدودیت اندازه ی حداکثر 900 بایتی هستند.
حال فرض کنید که قصد داریم SQL Server را محک زده و یک ایندکس بر روی ستونی از نوع (VARCHAR(8000 ایجاد کنیم و سپس رکوردهایی را با طول بیش از 900 بایت برای کلید ایندکس درج کنیم. فکر می کنید SQL Server چه عکس العملی نشان می دهد. خوب بهتر است که ایzzن مسئله را امتحان کنیم.
در کد زیر یک جدول ساده با یک ستون از نوع (VARCHAR(8000 ایجاد کرده و پس از آن یک ایندکس از نوع Non-Clustered بر روی این ستون ایجاد می کنیم.
[sql] — Create a simple table — Create a simple Non-Clustered Index |
با اجرای این کد SQL Server پیغام هشدار زیر را نمایش می دهد.
.Warning! The maximum key length is 900 bytes. The index ‘idx_Bar’ has maximum length of 8000 bytes
.For some combination of large values, the insert/update operation will fail
به این معنا که برای مقادیر بزرگ ممکن است دستورات INSERT یا UPDATE با خطا مواجه شوند.
و اما چیزی که اکنون اتفاق می افتد: قصد دارم یک رکورد با طول 901 بایت را در این ستون درج کنم.
[sql] — Insert a too large index key column… |
بله، مثل این که SQL Server هم حواسش به همه چیز هست. اجرای دستور INSERT من با خطای زیر مواجه شد.


SQL Server ابتدا اطمینان پیدا می کند که طول کلید در محدوده 900 بایت هست یا نه. در ادمه، می بینیم که SQL Server اجازه می دهد رکوردی با طول کلید دقیقا 900 بایت درج شود.
[sql] — Insert a too large index key column… |
کد فوق بدون هیچ خطایی اجرا می شود. حال در صورتی که این ستون را با مقداری بیش از 900 بایت بروزرسانی کنیم چه اتفاقی رخ می دهد.
[sql] — This UPDATE will fail |


اجرای دستور UPDATE نیز با خطا مواجه شد! که البته علت را می دانید. SQL Server ابتدا طول کلید را مورد بررسی قرار می دهد تا اطمینان بابد که در محدوده 900 بایت است یا خیر.
و اما نتیجه گیری که می توان کرد این است که، مهم نیست شما چقدر تلاش می کنید، SQL Server را نمی توانید دور بزنید، چون SQL Server حواسش به همه چیز هست.
نکته قابل توجه در اینجا این است که، با توجه به بررسی انجام شده، محدودیت 900 بایت برای کلید ایندکس تا SQL Server 2014 پا بر جا بوده است ولی در SQL Server 2016 این محدودیت به 1700 بایت افزایش پیدا کرده است. در صورتی که جدول و ایندکس فوق را در SQL Server 2016 ایجاد کنیم(من در نسخه RC3 تست کردم) با پیغام هشدار زیر مواجه خواهیم شد.
.Warning! The maximum key length for a nonclustered index is 1700 bytes. The index ‘idx_Bar’ has maximum length of 8000 bytes
.For some combination of large values, the insert/update operation will fail
در مورد INSERT و UPDATE نیز محدودیت 1700 بایت در نظر گرفته می شود و مشابه قبل خواهد بود.


در مورد ستون های نوع NVARCHAR نیز قضیه کاملا مشابه ستون های VARCHAR است، با این تفاوت که تمامی اندازه ها و محدودیت ها نصف می شود، زیرا در NVARCHAR به ازای هر کاراکتر 2 بایت اشغال می شود. بنابراین در صورتی که بخواهیم رکوردی را درج کنیم، کلید آن حداکثر می تواند دارای 450 کاراکتر باشد(چون برای ذخیره شدن 900 بایت اشغال می کند)، و در SQL Server 2016 کلید می تواند حداکثر دارای 850 کاراکتر باشد(چون برای ذخیره شدن 1700 بایت اشغال می کند).
در لینک زیر می توانید لیستی از حداکثر قابلیت های SQL Server که تا تاریخ 25/02/2016 منتشر شده است را مشاهده کنید.
بابت وقتی که گذاشتید تشکر می کنم
امیدوارم که این مقاله برای دوستان مفید باشد
سیدمحمد حسینی
خرداد ماه 1395
10 دیدگاه
مهدی شیشه بری شیشه بری
و اما نتیجه گیری که می توان کرد این است که، مهم نیست شما چقدر تلاش می
کنید، SQL Server را نمی توانید دور بزنید، چون SQL Server حواسش به همه
چیز هست.
چقدر خوب است که SQL حواسش به همه چیز است. موردی که باید یک الگو برای تیم های توسعه نرم افزارها باشد.
سپاس آقای حسینی
داود وحدانی
بسیار ممنون استفاده کردیم عالی بود و البته این قسمت منو یاد پلیس فتا میندازه که حواسش به همه چیز هست 🙂
حسن ضرابی
با سلام و خسته نباشید
ممنونم بابت این آموزشی که دادید جناب آقای مهندس سید محمد حسینی به نکات خیلی خوبی اشاره کردید.
ممنونم از شما
سیدمحمد حسینی
سلام
seyedmahdi
با تشکر از مقاله خوب شما
احسان زینلی
مقاله مختصر و مفیدی بود
ممنون
محمد دانشور
با تشکر از مطلب مفیدتون ،
من یه جدولی دارم که فیلد تاریخ آن عدد بوده و فیلد ساعت ان از نوع رشته(char) می باشد. و بر روی فیلد date, time ایندکس تعریف شده هست. وقتی دستور
select id from message order by date , time رو اجرا می کنم، با توجه به plan اس کیو ال از ایندکس موجود استفاده نمی کند ولی وقتی نوع داده فیلد ساعت رو به time تغییر می دهم ، از ایندکس تعریف شده استفاده می شود. آیا دلیل خاصی وجود دارد؟
ممنون می شم راهنمایی کنید.
محمد دانشور
توضیح این که در صورتی که Force کنیم اس کیو ال از ایندکس موجود استفاده کند. باز هم خودش عملیات Sort رو انجام می دهد.
محمد دانشور
در ضمن این مشکل فقط تو یه دیتا بیس وجود دارد. و در دیتابیس جدید از ایندکس استفاده می کند. و plan کوئری cost عملیات sort هم ندارد
محمد دانشور
بالاخره بعد از یک روز درگیری تونستم مشکل فوق رو حل کنم، collation دیتابیس روی latin بود و با تغییر collation فیلد رشته ای مورد نظر به arabic مشکل حل شد. ولی این که علتش چی بود . دقیقا نتونستم متوجه بشم!!!!
با تشکر