2017-03-03 91 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执行结果。请做'解释select ...'并检查'extra'列中的数据。如果只有'使用索引',那就完美了。如果没有'使用索引',看起来你的索引不起作用。 – degr

+0

尝试添加上'id_sistema_di_monitoraggio'一个[多列索引(https://dev.mysql.com/doc/refman/5.7/en/multiple-column-indexes.html),'id_unita','id_sensore'和'数据'。 – sp00m

+0

已有多列索引。 我在原始消息中添加了查询的解释。 – ghes86

回答

0
UNIQUE a(5), b(10) 

是可怕的。它表示只检查a的前5个字节以及b的前10个字节的唯一性。您可能想要检查完整的ab的组合以获得唯一性。

INDEX a(5), b(10) 

几乎是无用的 - 它不会让过去a甚至考虑b

INDEX a(5) 

有时无用。

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

通常是“错误的”。你确定a不能在一秒内出现两次吗?

查看多列索引时,“基数”通常并不重要。基数等于估计的表中的行数意味着它认为该列是唯一的;但它不会指望它。

“效率”,你的意思是“不占用太多的空间”?您的UNIQUE索引中的每个“行”将需要大约1 + 5 + 1 + 10 + 1 + 30 + 5 = 53个字节。多达317M,你得到17GB。增加约40%的开销以获得23GB。这比information_schema中的10GB多得多。 (错误涉及许多近似值 - 可能主要是行数。)

或者,您的意思是“该索引加快了某些查询”?为了讨论这个问题,我们需要看到这个查询。 (同时,我指出了指数不好的几个原因。)

如果ID号码

如果它们真的是数字,然后切换到SMALLINT UNSIGNED(2个字节)或一些其他的尺寸。 然后与4列(以及data最后)很可能显著加快该查询的索引。是的,该指数将花费一些磁盘空间,但它会可能是值得的。带有“前缀”的TEXT,根本不会提供效率。

而且索引号是不是字符串便宜。您的id_unita(10)在索引中的每一行最多占用11个字节; MEDIUMINT UNSIGNED需要固定的3个字节。也就是说,该指数将小更加有用。

+0

“高效”我的意思是“这个指数加快了我的查询速度?或者它没有好处需要很多空间?” :) 查询结果: '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通过数据;' – ghes86

+0

看到我的补充。 –