4

時間に基づいてほとんどのクエリを実行しています。だから私は作成された時間のインデックスを作成しました。しかし、インデックス付きの列のみを選択した場合、インデックスのみが機能します。mysql インデックスは選択した列に依存していますか?

インデックスに関する私の仮定

索引は電話辞書の索引ページのようなものだと思いました。例:「マーク」を見つけたい場合。索引ページは、ディレクトリ内で文字「M」が開始するページを示します。私はmysqlの作品と同じだと思います。

テーブル

+--------------+--------------+------+-----+---------+----------------+
| Field        | Type         | Null | Key | Default | Extra          |
+--------------+--------------+------+-----+---------+----------------+
| ID           | int(11)      | NO   | PRI | NULL    | auto_increment |
| Name         | varchar(100) | YES  |     | NULL    |                |
| OPERATION    | varchar(100) | YES  |     | NULL    |                |
| PID         | int(11)      | YES  |     | NULL    |                |
| CREATED_TIME | bigint(20)   | YES  |     | NULL    |                |
+--------------+--------------+------+-----+---------+----------------+

インデックス テーブルの上。

    +-----------+------------+----------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table     | Non_unique | Key_name | Seq_in_index | Column_name  | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------+------------+----------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| IndexTest |          0 | PRIMARY  |            1 | ID           | A         |       10261 |     NULL | NULL   |      | BTREE      |         |               |
| IndexTest |          1 | t_dx     |            1 | CREATED_TIME | A         |         410 |     NULL | NULL   | YES  | BTREE      |         |               |
+-----------+------------+----------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

インデックスを使用したクエリ:

   explain select * from IndexTest where ID < 5;
+----+-------------+-----------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table     | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+-----------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | IndexTest | range | PRIMARY       | PRIMARY | 4       | NULL |    4 | Using where |
+----+-------------+-----------+-------+---------------+---------+---------+------+------+-------------+



  explain select CREATED_TIME from IndexTest where CREATED_TIME > UNIX_TIMESTAMP(CURRENT_DATE())*1000;
    +----+-------------+-----------+-------+---------------+------+---------+------+------+--------------------------+
| id | select_type | table     | type  | possible_keys | key  | key_len | ref  | rows | Extra                    |
+----+-------------+-----------+-------+---------------+------+---------+------+------+--------------------------+
|  1 | SIMPLE      | IndexTest | range | t_dx          | t_dx | 9       | NULL | 5248 | Using where; Using index |
+----+-------------+-----------+-------+---------------+------+---------+------+------+--------------------------+

インデックスを使用しないクエリ

    explain select count(distinct(PID)) from IndexTest where CREATED_TIME > UNIX_TIMESTAMP(CURRENT_DATE())*1000;
+----+-------------+-----------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
+----+-------------+-----------+------+---------------+------+---------+------+-------+-------------+
|  1 | SIMPLE      | IndexTest | ALL  | t_dx          | NULL | NULL    | NULL | 10261 | Using where |
+----+-------------+-----------+------+---------------+------+---------+------+-------+-------------+


    explain select PID from IndexTest where CREATED_TIME > UNIX_TIMESTAMP(CURRENT_DATE())*1000;
+----+-------------+-----------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
+----+-------------+-----------+------+---------------+------+---------+------+-------+-------------+
|  1 | SIMPLE      | IndexTest | ALL  | t_dx          | NULL | NULL    | NULL | 10261 | Using where |
+----+-------------+-----------+------+---------------+------+---------+------+-------+-------------+
4

5 に答える 5

6

簡単な答え: いいえ。

WHEREインデックスが使用されるかどうかは、句の式などに依存しますが、JOIN選択した列には依存しません。

しかし、例外のないルールはありません (または実際にはそれらの長いリスト):

長い答え: 通常はありません

インデックスを使用する必要があるかどうかを判断するために、MySQL オプティマイザーが使用する要素は多数あります。

オプティマイザーは、次の場合にインデックスを無視することを決定する場合があります...

  • 別の(そうでなければ最適ではない)テーブルデータへのアクセスからそれをまったく保存します
  • 式が定数であることを理解していない
  • その見積もりは、とにかく完全なテーブルを返すことを示唆しています
  • その使用により一時ファイルが作成される場合
  • ...そして他にもたくさんの理由があり、そのうちのいくつかはどこにも文書化されていないようです

オプティマイザーによって行われる選択が... うーん... 最適とは言えない場合があります。これらの場合、あなたはどうしますか?

  • OPTIMIZE TABLEand/orを実行することで、オプティマイザを支援できますANALYZE TABLE。それは簡単で、時には役に立ちます。
  • USE INDEX(indexname)orFORCE INDEX(indexname)構文を使用して、特定のインデックスを使用するようにすることができます
  • IGNORE INDEX(indexname)次の構文で特定のインデックスを無視させることができます

MySQL ドキュメント Web サイトのIndex HintsOptimize TableおよびAnalyze Tableの詳細。

于 2013-03-29T16:39:42.560 に答える
4

実際には、列を選択してもしなくても違いはありません。インデックスはルックアップに使用されます。つまり、取得する必要があるレコードの数を非常に迅速に減らすことができます。これにより、通常、次のような状況で役立ちます。結合がある場合、where 条件がある場合。また、インデックスは順序付けに大いに役立ちます。

更新と削除は、where 条件でもインデックスを使用してかなり高速化できます。

例として:

table: id int pk ai, col1 ... indexed, col2 ...
select * from table -> does not use a index
select id from table where col1 = something -> uses the col1 index although it is not selected.

2 番目のクエリを見ると、mysql はインデックスでルックアップを行い、レコードを見つけ、この場合は停止して配信します (id と col1 の両方にインデックスがあり、id はたまたま pk であるため、2 番目のルックアップは必要ありません)。

この場合、状況が少し変わります。

select col2 from table where col1 = something

これにより、内部で 2 つのルックアップが作成されます。1 つは条件用、もう 1 つは col2 データを配信するための pk です。繰り返しになりますが、インデックスを使用するために col1 列を選択する必要はありません。

クエリに戻ると、問題は UNIX_TIMESTAMP(CURRENT_DATE())*1000; にあります。それを削除すると、インデックスがルックアップに使用されます。

于 2013-03-31T02:50:35.240 に答える
3

mysql インデックスは選択した列に依存していますか?

そのとおり。

: _

カラムがインデックスの左端のプレフィックスを形成していない場合、MySQL はインデックスを使用してルックアップを実行できません。次にSELECT示すステートメントがあるとします。

SELECT * FROM tbl_name WHERE col1=val1;
SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;

SELECT * FROM tbl_name WHERE col2=val2;
SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;

にインデックスが存在する場合(col1, col2, col3)、最初の 2 つのクエリだけがインデックスを使用します。3 番目と 4 番目のクエリには、インデックス付きの列が含まれますが、 の左端のプレフィックスではありませ(col2)ん。(col2, col3)(col1, col2, col3)

豊富なドキュメントを読んでください。

于 2013-03-20T10:37:38.693 に答える
0

インデックスを作成すると、テーブル データではなく、特定の列と関連データの検索が高速化されます。したがって、高速化するには、インデックス付きの列を含める必要がありますselect

于 2013-03-20T10:39:47.387 に答える