it-swarm.asia

لماذا لا يحتوي MySQL على مؤشرات التجزئة على MyISAM أو InnoDB؟

لدي تطبيق سيحدد فقط على المساواة ، وأظن أنني يجب أن أستخدم فهرس التجزئة على فهرس btree. مما يثير جزع الفزع أن مؤشرات التجزئة غير مدعومة على MyISAM أو InnoDB. ما الأمر مع ذلك؟

36
Alex

العديد من قواعد البيانات لا تدعم الفهارس القائمة على التجزئة على الإطلاق.

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

لذا ، لكي تكون مفيدًا بشكل عام (أي أفضل عادةً من البديل) ، يجب إعادة بناء الفهرس من حين لآخر مع نمو البيانات (وتقلصها) مما قد يؤدي إلى زيادة النفقات العامة المتقطعة. عادة ما يكون هذا جيدًا مع الجداول المستندة إلى الذاكرة حيث من المحتمل أن تكون إعادة البناء سريعة جدًا (حيث ستكون البيانات دائمًا في RAM وليس من المرجح أن تكون ضخمة في أي حال) ، لكن إعادة بناء فهرس كبير على القرص هي عملية ثقيلة جدًا (ولا يدعم IIRC mySQL عمليات إعادة بناء الفهرس المباشر ، لذا فهو يحمل قفل طاولة أثناء العملية).

ومن ثم يتم استخدام فهارس التجزئة في جداول الذاكرة حيث أنها أفضل أداءً بشكل عام ، ولكن الجداول القائمة على القرص لا تدعمها لأنها قد تضر على الأداء وليس مكافأة. لا يوجد شيء لوقف إتاحة فهارس التجزئة للجداول القائمة على القرص بالطبع ، لا شك في أن بعض قواعد البيانات تفعل تدعم الميزة ، ولكن من المفترض أنها لم يتم تنفيذها في جداول ISAM/InnoDB حيث لا يأخذ المشرفون بعين الاعتبار الميزة الجديرة بالإضافة (حيث أن الرمز الإضافي للكتابة والصيانة لا يستحق الفائدة في تلك الظروف القليلة التي يحدث فيها فرقًا كبيرًا). ربما إذا كنت لا توافق بشدة ، يمكنك التحدث معهم وتقديم مبرر جيد لتطبيق الميزة.

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

16
David Spillett

في ملاحظة ذات صلة ، قد تجد المناقشة حول أنواع الفهرس من مستندات PostgreSQL مثيرة للاهتمام. لم تعد موجودة في الإصدارات الأخيرة من المستندات (بسبب التحسينات اللاحقة ، أخذتها) ، ولكن قد تكون الوجبات الجاهزة مماثلة لـ MySQL (والسبب وراء استخدام فهارس التجزئة لجداول كومة الذاكرة المؤقتة فقط):

http://www.postgresql.org/docs/8.1/static/indexes-types.html

ملاحظة: أظهر الاختبار أن فهارس تجزئة PostgreSQL لا تؤدي أداءً أفضل من فهارس شجرة B ، كما أن حجم الفهرس ووقت بناء فهارس التجزئة أسوأ بكثير. علاوة على ذلك ، لا يتم تسجيل عمليات فهرسة التجزئة حاليًا في WAL ، لذا قد يلزم إعادة إنشاء فهارس التجزئة باستخدام REINDEX بعد تعطل قاعدة البيانات. لهذه الأسباب ، لا يُنصح باستخدام مؤشر التجزئة. وبالمثل ، لا يبدو أن لفهارس R-tree أي مزايا أداء مقارنة بالعمليات المكافئة لمؤشرات Gist. مثل فهارس التجزئة ، لم يتم تسجيلها في WAL وقد تحتاج إلى إعادة الفهرسة بعد تعطل قاعدة البيانات. في حين أنه قد يتم إصلاح مشاكل فهارس التجزئة في النهاية ، فمن المحتمل أن يتم إيقاف نوع فهرس R-tree في إصدار مستقبلي. يتم تشجيع المستخدمين على ترحيل التطبيقات التي تستخدم فهارس R-tree إلى فهارس Gist.

مرة أخرى ، إنه (إصدار قديم) خاص بـ PostgreSQL ، ولكن يجب أن يلمح إلى أن نوع الفهرس "الطبيعي" لن يؤدي بالضرورة إلى الأداء الأمثل.

6
Denis de Bernardy

هنا شيء مثير للاهتمام:

وفقًا للكتاب دليل دراسة شهادة MySQL 5. ، الصفحة 433 ، القسم 29.5.1

يستخدم محرك الذاكرة HASH عن طريق خوارزمية الفهرسة الافتراضية.

للضحك ، حاولت إنشاء جدول InnoDB وجدول MyISAM بمفتاح أساسي باستخدام HASH في MySQL 5.5.12

mysql> use test
Database changed
mysql> create table rolando (num int not null, primary key (num) using hash);
Query OK, 0 rows affected (0.11 sec)

mysql> show create table rolando\G
*************************** 1. row ***************************
       Table: rolando
Create Table: CREATE TABLE `rolando` (
  `num` int(11) NOT NULL,
  PRIMARY KEY (`num`) USING HASH
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

mysql> create table rolando2 (num int not null, primary key (num) using hash) engine=MyISAM;
Query OK, 0 rows affected (0.05 sec)

mysql> show create table rolando2\G
*************************** 1. row ***************************
       Table: rolando2
Create Table: CREATE TABLE `rolando2` (
  `num` int(11) NOT NULL,
  PRIMARY KEY (`num`) USING HASH
) ENGINE=MyISAM DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

لم يشكو MySQL.

تحديث

اخبار سيئة !!! لقد استخدمت SHOW INDEXES FROM. تقول أن المؤشر BTREE.

توضح صفحة إنشاء بنية MySQL أن محركات التخزين MEMORY و NDB فقط يمكنها استيعاب HASH INDEX.

mysql> show indexes from rolando;
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table   | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| rolando |          0 | PRIMARY  |            1 | num         | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)

mysql> show indexes from rolando2;
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table    | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| rolando2 |          0 | PRIMARY  |            1 | num         | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)

mysql> create table rolando3 (num int not null, primary key (num)) ENGINE=MEMORY;
Query OK, 0 rows affected (0.03 sec)

mysql> show create table rolando3\G
*************************** 1. row ***************************
       Table: rolando3
Create Table: CREATE TABLE `rolando3` (
  `num` int(11) NOT NULL,
  PRIMARY KEY (`num`)
) ENGINE=MEMORY DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

mysql> show indexes from rolando3;
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table    | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| rolando3 |          0 | PRIMARY  |            1 | num         | NULL      |           0 |     NULL | NULL   |      | HASH       |         |               |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)

اقترح بعض الأشخاص اتباع الفكرة في الصفحات 102-105 من الكتاب " MySQL عالي الأداء: التحسينات ، النسخ الاحتياطية ، النسخ المتماثل والمزيد " لمحاكاة خوارزمية التجزئة.

تتميز الصفحة 105 بهذه الخوارزمية السريعة والقذرة التي أحبها:

SELECT CONV(RIGHT(MD5('whatever value you want'),16),16,10) AS HASH64;

ضع عمودًا لهذا في أي جدول وفهرس هذه القيمة.

جربها !!!

5
RolandoMySQLDBA

BTree ليست أبطأ بكثير من Hash للبحث في صف واحد. نظرًا لأن BTree توفر استعلامات نطاق فعالة للغاية ، فلماذا تهتم بأي شيء آخر غير BTree.

يقوم MySQL بعمل تخزين مؤقت لكتل ​​BTree في التخزين المؤقت ، لذا نادرًا ما يتعين على الاستعلام المستند إلى BTree إجراء I/O ، وهو أكبر مستهلك للوقت في أي استعلام.

2
Rick James