2017-03-03 116 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

看到我的補充。 –