2017-03-03 13 views
3

私は次の表があります。私のMySQLインデックスは効率的ですか?

mysql> describe as_rilevazioni; 
+----------------------------+----------+------+-----+---------+----------------+ 
| Field      | Type  | Null | Key | Default | Extra   | 
+----------------------------+----------+------+-----+---------+----------------+ 
| id       | int(11) | NO | PRI | NULL | auto_increment | 
| id_sistema_di_monitoraggio | longtext | NO | MUL | NULL |    | 
| id_unita     | longtext | NO |  | NULL |    | 
| id_sensore     | longtext | NO |  | NULL |    | 
| data      | datetime | NO |  | NULL |    | 
| timestamp     | longtext | NO |  | NULL |    | 
| unita_di_misura   | longtext | NO |  | NULL |    | 
| misura      | longtext | NO |  | NULL |    | 
+----------------------------+----------+------+-----+---------+----------------+ 
8 rows in set (0.00 sec) 

私は私のテーブルの上にインデックス次き:

mysql> show indexes from as_rilevazioni; 
+----------------+------------+----------+--------------+----------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| Table   | Non_unique | Key_name | Seq_in_index | Column_name    | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | 
+----------------+------------+----------+--------------+----------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| as_rilevazioni |   0 | PRIMARY |   1 | id       | A   | 315865898 |  NULL | NULL |  | BTREE  |   |    | 
| as_rilevazioni |   0 | UNIQUE |   1 | id_sistema_di_monitoraggio | A   |   17 |  5 | NULL |  | BTREE  |   |    | 
| as_rilevazioni |   0 | UNIQUE |   2 | id_unita     | A   |   17 |  10 | NULL |  | BTREE  |   |    | 
| as_rilevazioni |   0 | UNIQUE |   3 | id_sensore     | A   |  145225 |  30 | NULL |  | BTREE  |   |    | 
| as_rilevazioni |   0 | UNIQUE |   4 | data      | A   | 315865898 |  NULL | NULL |  | BTREE  |   |    | 
+----------------+------------+----------+--------------+----------------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
5 rows in set (0.02 sec) 

私はコラム「データ」に基づいてインデックスのカーディナリティのようにあるので、これらのインデックスは効率的ではないかと思いますがレコードデータの数が多い! これらのインデックスはクエリの処理速度を上げるか、メリットなしで多くの領域を占有しますか?

これは、テーブル定義である:

CREATE TABLE `as_rilevazioni` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `id_sistema_di_monitoraggio` longtext NOT NULL, 
    `id_unita` longtext NOT NULL, 
    `id_sensore` longtext NOT NULL, 
    `data` datetime NOT NULL, 
    `timestamp` longtext NOT NULL, 
    `unita_di_misura` longtext NOT NULL, 
    `misura` longtext NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `UNIQUE` (`id_sistema_di_monitoraggio`(5),`id_unita`(10),`id_sensore`(30),`data`) 
) ENGINE=InnoDB AUTO_INCREMENT=437497044 DEFAULT CHARSET=latin1 

私が使用して、メインクエリは次のとおりです。

select * from as_rilevazioni where id_sistema_di_monitoraggio="<value>" and id_unita="<value>" and id_sensore="<value>" and data>="<date_1>" and data<="<date2>" 

これは、クエリでは、次のように説明し

mysql> explain select * from as_rilevazioni where id_sistema_di_monitoraggio="235" and id_unita="17" and id_sensore="15" and data >= "2015-01-01 00:00:00" order by data; 
+----+-------------+----------------+-------+---------------+--------+---------+------+--------+-------------+ 
| id | select_type | table   | type | possible_keys | key | key_len | ref | rows | Extra  | 
+----+-------------+----------------+-------+---------------+--------+---------+------+--------+-------------+ 
| 1 | SIMPLE  | as_rilevazioni | range | UNIQUE  | UNIQUE | 59  | NULL | 285522 | Using where | 
+----+-------------+----------------+-------+---------------+--------+---------+------+--------+-------------+ 
1 row in set (0.00 sec) 

これはの次元でデータとインデックス:

mysql> SELECT concat(table_schema,'.',table_name) tables, 
    ->  concat(round(table_rows/1000000,2),'M') rows, 
    ->  concat(round(data_length/(1024*1024*1024),2),'G') data_size, 
    ->  concat(round(index_length/(1024*1024*1024),2),'G') index_size, 
    ->  concat(round((data_length+index_length)/(1024*1024*1024),2),'G') total_size, 
    ->  round(index_length/data_length,2) index_data_ratio 
    -> FROM information_schema.TABLES 
    -> WHERE table_name="as_rilevazioni" 
    -> ORDER BY total_size DESC; 
+------------------------------------+---------+-----------+------------+------------+------------------+ 
| tables        | rows | data_size | index_size | total_size | index_data_ratio | 
+------------------------------------+---------+-----------+------------+------------+------------------+ 
| agriculturalsupport.as_rilevazioni | 317.12M | 19.06G | 10.25G  | 29.31G  |    0.54 | 
+------------------------------------+---------+-----------+------------+------------+------------------+ 
1 row in set (0.02 sec) 

提案がありますか? ありがとうございます!

+1

私はあなたが欲しいものを理解できません。あなたの質問に対する可能な回答 - 「はい」または「いいえ」。すべてが正しいように見えるので、私の答えは「はい」です。しかし、あなたの質問に答える一つの方法は、 'explain' SQL実行の結果だけです。 'explain select ...'を実行し、 'extra'カラムの中のデータをチェックしてください。 'use index'だけがあれば完璧です。 'use index'がなければ、あなたのインデックスのように見えません。 – degr

+0

'id_sistema_di_monitoraggio'、' id_unita'、 'id_sensore'に[マルチカラムインデックス](https://dev.mysql.com/doc/refman/5.7/en/multiple-column-indexes.html)を追加してみてください。と 'データ'。 – sp00m

+0

既に複数列のインデックスがあります。 元のメッセージにクエリの説明を追加します。 – ghes86

答えて

0
UNIQUE a(5), b(10) 

がひどい。 aの最初の5バイトだけと、最初の10バイトのbとの一意性をチェックするということです。一意であることを完全なabの組み合わせでチェックしたかったでしょう。

INDEX a(5), b(10) 

は事実上無用である - それもbを考慮することがa過去取得することはできません。

INDEX a(5) 

が時々役に立たないことがあります。

UNIQUE a, data -- where `data` is `DATETIME` or `TIMESTAMP` 

は通常間違っています。 aが1秒に2回表示されないことは本当に確かですか?

複数列のインデックスを参照する場合、「カーディナリティ」はしばしば重要ではありません。テーブル内のと推定されるカーディナリティがの行数であることは、の列が一意だと考えることを意味します。しかしそれはそれに数えられません。

「効率的」とは、「あまりにも多くのスペースを取らない」という意味ですか? UNIQUEインデックスの各「行」は約1 + 5 + 1 + 10 + 1 + 30 + 5 = 53バイトです。 317Mで倍増すると17GBになります。 23GBを得るためにオーバーヘッドのために約40%を追加してください。これはinformation_schemaの10GBよりもはるかに多いです。 (エラーには多くの近似が含まれていますが、ほとんどの場合行数になります)

または、「このインデックスはクエリを高速化しますか?これについて議論するには、クエリを見る必要があります。 (一方、私はインデックスが悪いいくつかの理由を指摘してきました。彼らは本当に数値であればIDは数字

している場合)

、そしてSMALLINT UNSIGNED(2バイト)、または他のいくつかのサイズに切り替えます。 これらの4つの列(およびdata最後の)のインデックスは、そのクエリを大幅に高速化する可能性が非常に高いです。はい、インデックスにはいくらかのディスク容量がかかりますが、、おそらくとなります。 TEXTは、 "プレフィックス"を付けても、単に効率を提供しません。

また、インデックス番号は文字列よりも安いです。 id_unita(10)は、インデックスの各行で最大11バイトを使用します。 MEDIUMINT UNSIGNEDは3バイト固定です。すなわち、指数はより小さくなりますもっと有用です。

+0

「効率的」とは、「このインデックスはクエリの速度を上げますか、それとも利益のために多くのスペースを必要としますか」という意味です。 :) クエリは: 'select * from as_rilevazioni id_sistema_di_monitoraggio =" 235 "、id_unita =" 17 "、id_sensore =" 15 "、データ> =" 2015-01-01 00:00:00 "データによって、 ' – ghes86

+0

私の追加を参照してください。 –

関連する問題