5

数千行を含むテーブルがあり、数値を含むVarchar列があります。この列が数値型ではない理由について説明したにもかかわらず、そのテーブルから行を選択すると、奇妙な動作が見られました。

その列にはインデックスがありますが、数値文字列を使用して行を検索する方が、Int(0.54秒)を使用するよりもはるかに高速(0.01秒)です。これの理由は何ですか?インデックスの値をキャストして使用できないようです...

私は何かを見落としていますか?インデックスに使用するためにIntをキャストしていないようです。インデックスの使用法に関するヒントを提供する必要がありますか、それともこれを実現するためのデータベーススイッチがありますか?または、Explainの出力を誤解した場合、なぜそれがそれほど遅くなるのですか?

例を示すテーブルレイアウト:

CREATE TABLE `example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `stuff` varchar(45) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_stuff` (`stuff`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ここでは、インデックスに文字列を使用しています。

explain select * from example where stuff='200';
----+-------------+---------+------+---------------+-----------+---------+-------+------+--------------------------+
| id | select_type | table   | type | possible_keys | key       | key_len | ref   | rows | Extra                    |
+----+-------------+---------+------+---------------+-----------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | example | ref  | idx_stuff     | idx_stuff | 137     | const |    1 | Using where; Using index |
+----+-------------+---------+------+---------------+-----------+---------+-------+------+--------------------------+

ここでは、インデックスの検索に使用する文字列にIntをキャストしていないようです。

explain select * from example where stuff=200;
+----+-------------+---------+-------+---------------+-----------+---------+------+------+--------------------------+
| id | select_type | table   | type  | possible_keys | key       | key_len | ref  | rows | Extra                    |
+----+-------------+---------+-------+---------------+-----------+---------+------+------+--------------------------+
|  1 | SIMPLE      | example | index | idx_stuff     | idx_stuff | 137     | NULL |    2 | Using where; Using index |
+----+-------------+---------+-------+---------------+-----------+---------+------+------+--------------------------+
4

2 に答える 2

12

マニュアルに記載されているように:

文字列列と数値を比較する場合、MySQLは列のインデックスを使用して値をすばやく検索することはできません。がインデックス付き文字列列の場合str_col、次のステートメントでルックアップを実行するときにインデックスを使用できません。

SELECT * FROM tbl_name WHERE str_col = 1;

この理由は、、、、1など、値に'1'変換される可能性のあるさまざまな文字列が多数あるため' 1'です'1a'

必要に応じCASTて、インデックスを利用するために、いつでも整数を文字列に変換できます。

SELECT * FROM example WHERE stuff = CAST(200 AS CHAR);
于 2012-05-08T00:15:51.900 に答える
6

警告: MySQLは、両方の値が。であっても、文字セットが一致しない場合はインデックスをスキップすることもありますCHAR。次のクエリが機能しない場合:

SELECT * FROM example WHERE stuff = CAST(200 AS CHAR);

次に、実行してデータベースの文字セットを取得し、次のようにステートメントshow variables like 'character_set_database';で使用します(この例では、データベースの文字セットが-であると想定しています。これを値に置き換えてください)。CONVERTlatin1character_set_database

SELECT * FROM example WHERE stuff = CONVERT(200 USING latin1);
于 2015-11-23T22:33:34.443 に答える