平等のみを選択するアプリケーションがあり、btreeインデックスよりもハッシュインデックスを使用する必要があると考えています。残念ながら、MyISAMまたはInnoDBではハッシュインデックスはサポートされていません。どうしたの?
平等のみを選択するアプリケーションがあり、btreeインデックスよりもハッシュインデックスを使用する必要があると考えています。残念ながら、MyISAMまたはInnoDBではハッシュインデックスはサポートされていません。どうしたの?
回答:
多くのデータベースはハッシュベースのインデックスを全くサポートしていません。
ハッシュテーブルを効率的にするには、存在する可能性のある行の数を知る必要があります。そうしないと、ベースハッシュテーブルが非常に大きくなります(多くの空のエントリ、無駄なスペース、潜在的にディスクIO)または多くの場合、インダイレクションが使用されます(おそらく複数レベルのインダイレクション、またはハッシュ実装が単一レベルの場合はかなりの数のレコードに対して線形検索を実行する可能性があります)。とにかくインデックス。
そのため、一般的に役立つ(つまり、通常よりも優れている)ために、データが大きくなる(および小さくなる)ときにインデックスを時々再構築する必要があり、これにより大きな断続的なオーバーヘッドが追加されます。これは通常、メモリベースのテーブルでは問題ありません。再構築はおそらく非常に高速になるためです(データは常にRAMに格納され、いずれの場合も大規模になる可能性は低いため)が、ディスク上の大きなインデックスの再構築は非常に重い操作(およびIIRC mySQLはライブインデックスの再構築をサポートしないため、操作中にテーブルロックを保持します)。
したがって、ハッシュインデックスは一般にパフォーマンスが向上するためメモリテーブルで使用されますが、ディスクベースのテーブルはボーナスではなくパフォーマンスを損なう可能性があるため、それらをサポートしません。もちろん、ディスクベースのテーブルでハッシュインデックスが使用可能になるのを止めるものはありません。一部のデータベースはこの機能をサポートしていることは間違いありませんが、メンテナーは追加する価値のある機能を考慮していないため、おそらくISAM / InnoDBテーブルには実装されていません記述して保守する余分なコードは、重要な違いを生むこれらの少数の状況ではメリットがありません)。おそらくあなたが強く同意しないなら、彼らと話をして、機能の実装について良いケースを作ることができます。
大きな文字列のインデックスを作成する場合、独自の擬似ハッシュインデックスの実装(値と実際の値のハッシュを格納し、列を持つインデックスを作成することで)が機能する場合がありますが、これは大きな文字列の場合にのみより確実に効率的です(ここでハッシュ値の計算とこの値によるツリーインデックスの検索は、比較のために大きな値を使用してツリーインデックスを検索するよりも常に高速である可能性が高く、使用される追加のストレージは重要ではありません)これは生産中です。
関連する注意事項として、PostgreSQLドキュメントのインデックスタイプに関する説明が興味深い場合があります。ドキュメントの最近のバージョンには存在しません(その後の最適化のため、私はそれを採用します)が、MySQLでも同様です(そして、ハッシュインデックスがヒープテーブルにのみ使用される理由):
http://www.postgresql.org/docs/8.1/static/indexes-types.html
注:テストの結果、PostgreSQLのハッシュインデックスはBツリーインデックスよりも性能が劣ることが示されており、ハッシュインデックスのインデックスサイズと構築時間ははるかに劣っています。さらに、ハッシュインデックス操作は現在WALログに記録されていないため、データベースのクラッシュ後にハッシュインデックスをREINDEXで再構築する必要があります。これらの理由により、ハッシュインデックスの使用は現在推奨されていません。同様に、Rツリーインデックスには、GiSTインデックスの同等の操作と比較してパフォーマンス上の利点はないようです。ハッシュインデックスと同様に、WALに記録されず、データベースのクラッシュ後にインデックスの再作成が必要になる場合があります。ハッシュインデックスの問題は最終的に修正される可能性がありますが、Rツリーインデックスタイプは将来のリリースで廃止される可能性があります。Rツリーインデックスを使用するアプリケーションをGiSTインデックスに移行することをお勧めします。
繰り返しますが、これはPostgreSQL固有の(旧バージョン)ですが、「自然な」インデックスタイプでは必ずしも最適なパフォーマンスが得られないことを示唆するはずです。
ここに興味深いものがあります:
本によるMySQLの5.0認定研究ガイド、ページ433、セクション29.5.1
MEMORYエンジンは、デフォルトのインデックス作成アルゴリズムによりHASHを使用します。
笑いのために、MySQL 5.5.12でHASHを使用して主キーを持つInnoDBテーブルとMyISAMテーブルを作成しようとしました
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であると表示されます。
INDEX構文MySQLのページには、CREATE専用メモリとNDBストレージエンジンは、ハッシュインデックスに対応できると述べています。
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)
一部の人々は、「High Performance MySQL:Optimizations、Backups、Replication and More」という本のページ102-105のアイデアに従って、ハッシュアルゴリズムをエミュレートすることを提案しました。
ページ105には、私が気に入っているこの手っ取り早いアルゴリズムがあります。
SELECT CONV(RIGHT(MD5('whatever value you want'),16),16,10) AS HASH64;
任意のテーブルにこの列を作成し、この値にインデックスを付けます。
試してみる !!!