it-swarm.asia

ما هو تأثير أداء استخدام CHAR مقابل VARCHAR في حقل ثابت الحجم؟

لدي عمود مفهرس يقوم بتخزين تجزئة MD5. وبالتالي ، سيخزن العمود دائمًا قيمة مكونة من 32 حرفًا. لأي سبب من الأسباب ، تم إنشاء هذا على أنه varchar بدلاً من char. هل يستحق عناء ترحيل قاعدة البيانات لتحويلها إلى حرف؟ هذا في MySQL 5.0 مع InnoDB.

60
Jason Baker

تم طرح سؤال مماثل من قبل

الآثار المترتبة على أداء MySQL VARCHAR الأحجام

هنا مقتطف من إجابتي

يجب أن تدرك المقايضات باستخدام CHAR vs VARCHAR

مع حقول CHAR ، ما تخصصه هو بالضبط ما تحصل عليه. على سبيل المثال ، تقوم CHAR (15) بتخصيص وتخزين 15 بايت ، بغض النظر عن كيفية وضع الأحرف في الحقل. يعد التلاعب بالسلسلة أمرًا بسيطًا ومباشرًا لأن حجم مجال البيانات يمكن التنبؤ به تمامًا.

مع حقول VARCHAR ، تحصل على قصة مختلفة تمامًا. على سبيل المثال ، يخصص VARCHAR (15) ديناميكيًا حتى 16 بايت ، وما يصل إلى 15 للبيانات ، وعلى الأقل بايت إضافي واحد لتخزين طول البيانات. إذا كان لديك السلسلة "hello" لتخزينها والتي ستستغرق 6 بايت ، وليس 5. يجب أن يؤدي التلاعب بالسلسلة دائمًا إلى شكل من أشكال التحقق من الطول في جميع الحالات.

تكون المفاضلة أكثر وضوحًا عند القيام بأمرين: 1. تخزين ملايين أو مليارات الصفوف 2. أعمدة الفهرسة التي إما CHAR أو VARCHAR

TRADEOFF # 1 من الواضح أن VARCHAR تتمتع بالميزة لأن البيانات ذات الطول المتغير ستنتج صفوفًا أصغر ، وبالتالي ملفات فعلية أصغر.

TRADEOFF # 2 بما أن حقول CHAR تتطلب معالجة سلسلة أقل بسبب عرض الحقول الثابت ، فإن عمليات البحث في الفهرس مقابل حقل CHAR هي في المتوسط ​​أسرع بنسبة 20٪ من حقول VARCHAR. هذا ليس أي تخمين من جهتي. قام كتاب تصميم وقاعدة بيانات MySQL بعمل شيء رائع على طاولة MyISAM لإثبات ذلك. فعل المثال في الكتاب شيئًا مثل ما يلي:

ALTER TABLE tblname ROW_FORMAT=FIXED;

يجبر هذا التوجيه جميع VARCHARs على التصرف كأحرف. لقد فعلت ذلك في وظيفتي السابقة في عام 2007 وأخذت جدولًا بسعة 300 جيجابايت وسرعت عمليات البحث في الفهرس بنسبة 20٪ ، دون تغيير أي شيء آخر. عملت كما نشرت. ومع ذلك ، فقد أنتج جدولًا بحجم مضاعف تقريبًا ، ولكن هذا ببساطة يعود إلى المفاضلة رقم 1.

يمكنك تحليل البيانات التي يتم تخزينها لمعرفة ما يوصي به MySQL لتعريف العمود. فقط قم بتشغيل ما يلي مقابل أي جدول:

SELECT * FROM tblname PROCEDURE ANALYSE();

سيؤدي هذا إلى اجتياز الجدول بالكامل والتوصية بتعريفات الأعمدة لكل عمود استنادًا إلى البيانات التي يحتوي عليها ، والحد الأدنى لقيم الحقول ، والحد الأقصى لقيم الحقول ، وما إلى ذلك. في بعض الأحيان ، عليك فقط استخدام الحس السليم مع التخطيط CHAR مقابل VARCHAR. هنا هو مثال جيد:

إذا كنت تقوم بتخزين عناوين IP ، فإن القناع الخاص بهذا العمود لا يزيد عن 15 حرفًا (xxx.xxx.xxx.xxx). سوف أقفز بسرعة عند CHAR(15) في ضربات قلب لأن أطوال عناوين IP لن تختلف كثيرًا والتعقيد الإضافي لمعالجة السلسلة الذي يتحكم فيه بايت إضافي. لا يزال بإمكانك إجراء PROCEDURE ANALYSE() مقابل هذا العمود. قد يوصي حتى VARCHAR. ستظل أموالي على CHAR عبر VARCHAR في هذه الحالة.

لا يمكن حل مشكلات CHAR vs VARCHAR إلا من خلال التخطيط المناسب. مع القوة العظيمة تأتي مسؤولية كبيرة (مبتذلة لكنها حقيقية).

تحديث

عندما يتعلق الأمر بـ MD5 ، يجب التخلص من حساب strlen داخليًا عند تبديل تنسيق الصف بأكمله. لن تكون هناك حاجة لتغيير تعريف المجال.

إذا كان مفتاح MD5 هو VARCHAR الوحيد الموجود ، سأذهب إليه وقم بتحويل تنسيق صف الجدول إلى ثابت . إذا كان هناك عدد كبير من حقول VARCHAR الأخرى الموجودة ، فستستفيد أيضًا. في المقابل ، سيتم توسيع الجدول إلى حوالي ضعف حجمه. ولكن يجب أن تسرع الاستعلامات حوالي 20٪ أكثر بدون ضبط إضافي.

57
RolandoMySQLDBA

يبدو أنك ستوفر 1 بايت لكل قيمة أو حوالي 3٪ عن طريق التحويل إلى char. ربما لا يستحق ذلك إذا كنت تقوم بتخزين MD5 في ست عشري على أي حال - يمكنك توفير 50 ​​٪ باستخدام binary بدلاً من ذلك.

بفضل Ovais (انظر التعليقات) للإشارة إلى أن char(32) يمكنها استخدام أكثر من 32 بايت إذا كنت تستخدم مجموعة أحرف متعددة البايت.

بفضل ريك جيمس للإشارة إلى أنه يجب عليك استخدام الدالة unhex لتحويل السلسلة السداسية إلى ثنائي:

create table foo(bar varbinary(100));
insert into foo(bar) values(md5('a')); 
insert into foo(bar) values(unhex(md5('a'))); 
select length(bar) from foo;
 | طول (شريط) | 
 | ----------: | 
 | 32 | 
 | 16 | 

ديسيبل <> كمان هنا

19
Jack says try topanswers.xyz

لا يستحق التغيير في رأيي. إذا نظرت في الوثائق هنا يجب أن توضح الفرق بين الاثنين. في سيناريو الاستخدام الخاص بك ، لا يقدم أحدهما أي فائدة كبيرة على الآخر إلا إذا كنت مهتمًا حقًا بالجزء الإضافي من النفقات العامة المتعلقة بحجم الصف.

http://dev.mysql.com/doc/refman/5.0/en/char.html

لاحظ أيضًا التعليق الأول على الوثائق التي أرتبط بها أعلاه ... "CHAR سوف تسرع وصولك فقط إذا كان السجل بأكمله بحجم ثابت. أي ، إذا كنت تستخدم أي كائن متغير الحجم ، يمكنك أيضًا جعلهم جميعًا متغير الحجم. لن تكسب أي سرعة باستخدام CHAR في جدول يحتوي أيضًا على VARCHAR "

15
RThomas