草庐IT

mysql - 我的 MySQL 索引是否有效?

coder 2023-10-26 原文

我有下表:

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)

有什么建议吗? 感谢大家!

最佳答案

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 字节)或其他一些大小。 Then 包含这 4 列(和 data last)的索引很可能会显着加快该查询的速度。是的,索引会占用一些磁盘空间,但可能是值得的。 TEXT,带有“前缀”,根本不会提供效率。

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

关于mysql - 我的 MySQL 索引是否有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42577556/

有关mysql - 我的 MySQL 索引是否有效?的更多相关文章

  1. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  2. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  3. ruby - 如何进行排列以有效地定制输出 - 2

    这是一道面试题,我没有答对,但还是很好奇怎么解。你有N个人的大家庭,分别是1,2,3,...,N岁。你想给你的大家庭拍张照片。所有的家庭成员都排成一排。“我是家里的friend,建议家庭成员安排如下:”1岁的家庭成员坐在这一排的最左边。每两个坐在一起的家庭成员的年龄相差不得超过2岁。输入:整数N,1≤N≤55。输出:摄影师可以拍摄的照片数量。示例->输入:4,输出:4符合条件的数组:[1,2,3,4][1,2,4,3][1,3,2,4][1,3,4,2]另一个例子:输入:5输出:6符合条件的数组:[1,2,3,4,5][1,2,3,5,4][1,2,4,3,5][1,2,4,5,3][

  4. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  5. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  6. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

  7. ruby - 检查日期是否在过去 7 天内 - 2

    我的日期格式如下:"%d-%m-%Y"(例如,今天的日期为07-09-2015),我想看看是不是在过去的七天内。谁能推荐一种方法? 最佳答案 你可以这样做:require"date"Date.today-7 关于ruby-检查日期是否在过去7天内,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/32438063/

  8. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  9. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

  10. ruby - 我可以将我的 README.textile 以正确的格式放入我的 RDoc 中吗? - 2

    我喜欢使用Textile或Markdown为我的项目编写自述文件,但是当我生成RDoc时,自述文件被解释为RDoc并且看起来非常糟糕。有没有办法让RDoc通过RedCloth或BlueCloth而不是它自己的格式化程序运行文件?它可以配置为自动检测文件后缀的格式吗?(例如README.textile通过RedCloth运行,但README.mdown通过BlueCloth运行) 最佳答案 使用YARD直接代替RDoc将允许您包含Textile或Markdown文件,只要它们的文件后缀是合理的。我经常使用类似于以下Rake任务的东西:

随机推荐