MySQL索引导致查询变慢

MySQL索引导致查询变慢,mysql,performance,indexing,Mysql,Performance,Indexing,我有一个MySQL表,其中包含大约2000万行数据 +-------------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+-------------+------+-----+---------+----------------+ | id

我有一个MySQL表,其中包含大约2000万行数据

+-------------+-------------+------+-----+---------+----------------+
| Field       | Type        | Null | Key | Default | Extra          |
+-------------+-------------+------+-----+---------+----------------+
| id          | bigint(20)  | NO   | PRI | NULL    | auto_increment |
| b_id        | int(11)     | YES  | MUL | NULL    |                |
| order       | bigint(20)  | YES  | MUL | NULL    |                |
| date        | date        | YES  |     | NULL    |                |
| time        | time        | YES  |     | NULL    |                |
| channel     | varchar(8)  | YES  | MUL | NULL    |                |
| data        | varchar(60) | YES  |     | NULL    |                |
| date_system | date        | YES  | MUL | NULL    |                |
| time_system | time        | YES  |     | NULL    |                |
+-------------+-------------+------+-----+---------+----------------+
我在(b_id、channel、date)上有一个非唯一索引,可以加快查询速度,如:

select date, left(time,2) as hour, round(data,1) as data
from data_lines
where channel='1'
  and b_id='300'
  and date >='2013-04-19'
  and date <='2013-04-26' 
group by date,hour

尝试在查询中显式指定
使用索引(更新索引)

优化器在选择索引时做出了错误的选择,因为这会导致查询速度变慢

希望这能解决您的问题:)

  • 由于
    主键
    是一个
    唯一键
    ,因此请去掉无用的
    唯一(id)
  • 我们正在讨论的任何列是否为空?如果不是,则使它们
    不为NULL
    。(这在升级
    UNIQUE
    索引之前很重要。)
  • 除非您在其他查询中需要它,
    DROP
    comp\u index
    。它在4列
    唯一索引
    上不提供额外的好处(对于您的
    插入
    选择
  • 您是否在其他任何地方使用
    id
    ?如果不是,则将4列唯一索引提升为
    主键
    。这一步可能会加快速度,因为现在它不会在索引和数据之间来回跳转(以获取
    数据
  • 剩下4个其他指标;看看你是否真的需要它们。(我建议这样做是因为上一步将使二级索引更庞大。)
  • 如果您正在使用MyISAM,请更改为InnoDB
当执行大量的
更改时,请在一条语句中执行这些更改,这样会快得多

ALTER TABLE ...
    DROP COLUMN id,
    DROP PRIMARY KEY,
    DROP INDEX `id_UNIQUE`,
    DROP INDEX comp_index,
    ADD PRIMARY KEY(channel, b_id, date, time),
    ALTER COLUMN ... NOT NULL,
    ...
    ENGINE=InnoDB;
或者,更为谨慎的是:
创建修改后的表,然后
插入…选择
填充它。然后测试。最后,重新命名表以将其放置到位


通常,将
日期
时间
分为两列而不是一列
日期时间
是一个坏主意。但是我不会推它,因为它可能对这个问题影响不大。

请为您的查询显示
explain
语句。。您创建的所有索引..嗨,Meherzad,谢谢您的帮助。在我上面的帖子中添加了explain命令来设置格式。请尝试显式指定
使用索引(update\u INDEX)
。这似乎可以解决select命令的速度慢的问题。谢谢出于好奇,我可以通过删除comp_索引得到同样的结果吗?这样做是否明智(如果我不再使用它)?@Meherzad:如果你提供你的评论作为答案,我肯定会批准!我在读
我们正在讨论的任何列都是空的吗?如果不是,则使其不为NULL。(在升级唯一索引之前,这一点很重要。)
根据高性能SQL第三版,我认为这不再适用于InnoDB数据库,该版本规定“InnoDB使用一个位存储空值,因此对于人口稀少的数据,它可以非常节省空间”@ alalWang-但您使用的是什么<代码> RoopFrase?@ ALWAN——也请阅读关于<代码> NUL> /COD>值在使用<代码> > <代码> >索引时是否认为不相等的问题。
+-----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table     | Non_unique | Key_name     | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| data_lines|          0 | PRIMARY      |            1 | id          | A         |    17918898 |     NULL | NULL   |      | BTREE      |         |               |
| data_lines|          0 | id_UNIQUE    |            1 | id          | A         |    17918898 |     NULL | NULL   |      | BTREE      |         |               |
| data_lines|          0 | update_index |            1 | channel     | A         |          17 |     NULL | NULL   | YES  | BTREE      |         |               |
| data_lines|          0 | update_index |            2 | b_id        | A         |          17 |     NULL | NULL   | YES  | BTREE      |         |               |
| data_lines|          0 | update_index |            3 | date        | A         |       44244 |     NULL | NULL   | YES  | BTREE      |         |               |
| data_lines|          0 | update_index |            4 | time        | A         |    17918898 |     NULL | NULL   | YES  | BTREE      |         |               |
| data_lines|          1 | box_id       |            1 | b_id        | A         |          17 |     NULL | NULL   | YES  | BTREE      |         |               |
| data_lines|          1 | idx          |            1 | order       | A         |    17918898 |     NULL | NULL   | YES  | BTREE      |         |               |
| data_lines|          1 | comp_index   |            1 | b_id        | A         |          17 |     NULL | NULL   | YES  | BTREE      |         |               |
| data_lines|          1 | comp_index   |            2 | channel     | A         |        6624 |     NULL | NULL   | YES  | BTREE      |         |               |
| data_lines|          1 | comp_index   |            3 | date        | A         |      165915 |     NULL | NULL   | YES  | BTREE      |         |               |
| data_lines|          1 | date_system  |            1 | date_system | A         |          17 |     NULL | NULL   | YES  | BTREE      |         |               |
| data_lines|          1 | mac          |            1 | mac         | A         |          17 |     NULL | NULL   | YES  | BTREE      |         |               |
+-----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
ALTER TABLE ...
    DROP COLUMN id,
    DROP PRIMARY KEY,
    DROP INDEX `id_UNIQUE`,
    DROP INDEX comp_index,
    ADD PRIMARY KEY(channel, b_id, date, time),
    ALTER COLUMN ... NOT NULL,
    ...
    ENGINE=InnoDB;