3

tick最大のレコードの値を読み取っていますid。実行を遅くする原因となる次のクエリの違いは何ですか?

遅いクエリ:

SELECT tick
FROM   eventlog
WHERE  id IN (SELECT max(id) FROM eventlog)

クイッククエリ:

SELECT max(id) INTO @id
FROM   eventlog;

SELECT tick
FROM   eventlog
WHERE  id = @id;

スキーマ

CREATE TABLE eventlog (
    id INT (11) NOT NULL AUTO_INCREMENT,
    tick INT NOT NULL,
    eventType_id INT NOT NULL,
    compType INT (10) UNSIGNED NOT NULL,
    compID INT (10) UNSIGNED NOT NULL,
    value_double DOUBLE NOT NULL,
    value_int INT (10),
    hierarchy_id VARCHAR (255) NOT NULL,
    PRIMARY KEY (id),
    INDEX htet (
        hierarchy_id,
        tick,
        eventType_id
    )
)
4

2 に答える 2

5

クエリプランを見てみてください。その場合、DBMSはおそらくインデックスを使用できません。クエリを次のように変更してみてください。

SELECT tick
FROM   eventlog
WHERE  id = (SELECT max(id) FROM eventlog)

編集 実際には、おそらくそれを行うためのより良い方法があります。上記のクエリでは、2つのINDEX ACCESS操作(または、インデックスが一意でない場合はさらに1つのINDEX RANGE SCAN)と1つのTABLEACCESSを実行します。代わりに、次のことができます。

SELECT tick
FROM   eventlog
ORDER BY id DESC
LIMIT 1

これを使用すると、1つのINDEXACCESSと1つのTABLEACCESSが必要になります。実際、TABLE ACCESSは非常にコストのかかる操作であるため、違いはかなり小さい可能性があります。そのため、ビッグデータセットでは違いが見られる場合があります。

于 2012-09-18T07:01:20.627 に答える
5

inクエリはインデックスを使用しないため、mysqlはすべてのレコードをスキャンして行を検索します。

http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.htmlから

Bツリーインデックスの特性

Bツリーインデックスは、=、>、> =、<、<=、またはBETWEEN演算子を使用する式の列比較に使用できます。

ありませんIN

ハッシュインデックスの特性

ハッシュインデックスには、今説明したものとは多少異なる特性があります。

これらは、=または<=>演算子を使用する等式比較にのみ使用されます(ただし、非常に高速です)。これらは、値の範囲を見つける<などの比較演算子には使用されません。

どちらもありませんIN

@tombomが述べたように、のfoo IN ('bar', 'bla')略ですfoo = 'bar' OR foo = 'bla'が、私はそれらが異なっていると信じています。そこで、十分なデータレコードがあるテーブルでテストを行い、次のことを確認します。

mysql> show columns from t_key;   
+-------+---------+------+-----+---------+----------------+
| Field | Type    | Null | Key | Default | Extra          |
+-------+---------+------+-----+---------+----------------+
| a     | int(11) | NO   | PRI | NULL    | auto_increment |
| b     | int(11) | YES  | MUL | NULL    |                |
+-------+---------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

mysql> select count(a) from t_key;
+----------+
| count(a) |
+----------+
|   989901 |
+----------+
1 row in set (0.00 sec)

mysql> explain select a from t_key where a in (select max(a) from t_key);  
+----+--------------------+-------+-------+---------------+---------+---------+------+--------+------------------------------+
| id | select_type        | table | type  | possible_keys | key     | key_len | ref  | rows   | Extra                        |
+----+--------------------+-------+-------+---------------+---------+---------+------+--------+------------------------------+
|  1 | PRIMARY            | t_key | index | NULL          | PRIMARY | 4       | NULL | 989901 | Using where; Using index     |
|  2 | DEPENDENT SUBQUERY | NULL  | NULL  | NULL          | NULL    | NULL    | NULL |   NULL | Select tables optimized away |
+----+--------------------+-------+-------+---------------+---------+---------+------+--------+------------------------------+
2 rows in set (0.00 sec)

mysql> explain select a from t_key where a =(select max(a) from t_key);
+----+-------------+-------+-------+---------------+---------+---------+-------+------+------------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref   | rows | Extra                        |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+------------------------------+
|  1 | PRIMARY     | t_key | const | PRIMARY       | PRIMARY | 4       | const |    1 | Using index                  |
|  2 | SUBQUERY    | NULL  | NULL  | NULL          | NULL    | NULL    | NULL  | NULL | Select tables optimized away |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+------------------------------+
2 rows in set (0.00 sec)

次にIN、静的シーケンスを使用してクエリを試します。これは、@tombomが述べたように機能します。

mysql> explain select a from t_key where a in (100,200);
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                    |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
|  1 | SIMPLE      | t_key | range | PRIMARY       | PRIMARY | 4       | NULL |    2 | Using where; Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

mysql> explain select a from t_key where a=100 or a=200;
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                    |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
|  1 | SIMPLE      | t_key | range | PRIMARY       | PRIMARY | 4       | NULL |    2 | Using where; Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

IN可能な場合にmysqlがクエリを1つに変換するかどうかはわかりませんORs(たとえば、シーケンスはクエリの前にわかっています)。関連するドキュメントは見つかりませんでしたがexplain、この状況でテーブルをスキャンしたことが示されています。

于 2012-09-18T07:14:06.940 に答える