添加唯一约束会减慢速度吗?

时间:2010-10-05 01:01:30

标签: sql mysql database query-optimization

我的桌子上有三列。

+-----------+-----------------------+------+-----+---------+-------+
| Field     | Type                  | Null | Key | Default | Extra |
+-----------+-----------------------+------+-----+---------+-------+
| hash      | mediumint(8) unsigned | NO   | PRI | 0       |       | 
| nums      | int(10) unsigned      | NO   | PRI | 0       |       | 
| acc       | smallint(5) unsigned  | NO   | PRI | 0       |       | 
+-----------+-----------------------+------+-----+---------+-------+

我期待我的数据重复,所以我继续添加了一个独特的约束:

ALTER TABLE nt_accs ADD UNIQUE(hash,nums,acc);

我有大约5亿行要插入到此表中,并且该表已经使用RANGE在nums上分成大约20个分区。

  1. 唯一约束会减慢插入吗?这只是在制作主键而不是强加一个唯一约束时有何不同?
  2. 我使用hash和nums列进行了大量GROUP BY类型查询。我是否继续添加convering index,或者我只是添加单个索引?
  3. 修改

    分区并插入一些测试数据后解释计划

    1. mysql> explain partitions select * from nt_accs;
    +----+-------------+-----------+---------------------------------------------------------------------------+-------+---------------+----------+---------+------+------+-------------+
    | id | select_type | table     | partitions                                                                | type  | possible_keys | key      | key_len | ref  | rows | Extra       |
    +----+-------------+-----------+---------------------------------------------------------------------------+-------+---------------+----------+---------+------+------+-------------+
    |  1 | SIMPLE      | nt_accs   | p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20 | index | NULL          | hash     | 7       | NULL |   10 | Using index | 
    +----+-------------+-----------+---------------------------------------------------------------------------+-------+---------------+----------+---------+------+------+-------------+
    1 row in set (0.00 sec)
    
    
    
    2. mysql> explain partitions select * from nt_accs WHERE nums=1504887570;
    +----+-------------+-----------+------------+-------+---------------+----------+---------+------+------+--------------------------+
    | id | select_type | table     | partitions | type  | possible_keys | key      | key_len | ref  | rows | Extra                    |
    +----+-------------+-----------+------------+-------+---------------+----------+---------+------+------+--------------------------+
    |  1 | SIMPLE      | nt_accs   | p7         | index | NULL          | hash     | 7       | NULL |   10 | Using where; Using index | 
    +----+-------------+-----------+------------+-------+---------------+----------+---------+------+------+--------------------------+
    1 row in set (0.00 sec)
    
    3. mysql> explain partitions select * from nt_accs WHERE hash=2347200;
    +----+-------------+-----------+---------------------------------------------------------------------------+------+---------------+----------+---------+-------+------+-------------+
    | id | select_type | table     | partitions                                                                | type | possible_keys | key      | key_len | ref   | rows | Extra       |
    +----+-------------+-----------+---------------------------------------------------------------------------+------+---------------+----------+---------+-------+------+-------------+
    |  1 | SIMPLE      | nt_accs  | p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20 | ref  | hash          | hash     | 3       | const |   27 | Using index | 
    +----+-------------+-----------+---------------------------------------------------------------------------+------+---------------+----------+---------+-------+------+-------------+
    1 row in set (0.00 sec)
    
    4. mysql> EXPLAIN PARTITIONS SELECT hash, count(distinct nums) FROM nt_accs GROUP BY hash;
    +----+-------------+-----------+---------------------------------------------------------------------------+-------+---------------+----------+---------+------+------+-------------+
    | id | select_type | table     | partitions                                                                | type  | possible_keys | key      | key_len | ref  | rows | Extra       |
    +----+-------------+-----------+---------------------------------------------------------------------------+-------+---------------+----------+---------+------+------+-------------+
    |  1 | SIMPLE      | nt_accs   | p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20 | index | NULL          | hash     | 7       | NULL |   10 | Using index | 
    +----+-------------+-----------+---------------------------------------------------------------------------+-------+---------------+----------+---------+------+------+-------------+
    1 row in set (0.00 sec)
    
    5. mysql> EXPLAIN PARTITIONS SELECT nums, count(distinct hash) FROM nt_accs GROUP BY nums;
    +----+-------------+-----------+---------------------------------------------------------------------------+-------+---------------+----------+---------+------+------+-----------------------------+
    | id | select_type | table     | partitions                                                                | type  | possible_keys | key      | key_len | ref  | rows | Extra                       |
    +----+-------------+-----------+---------------------------------------------------------------------------+-------+---------------+----------+---------+------+------+-----------------------------+
    |  1 | SIMPLE      | nt_accs   | p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20 | index | NULL          | hash     | 7       | NULL |   10 | Using index; Using filesort | 
    +----+-------------+-----------+---------------------------------------------------------------------------+-------+---------------+----------+---------+------+------+-----------------------------+
    1 row in set (0.00 sec)
    

    我对第一次和第二次查询完全没问题,但我不确定第3,第4和第5次的表现。在这一点上我还能做些什么来优化这个吗?

1 个答案:

答案 0 :(得分:8)

  

唯一约束会减慢插入吗?这与仅制作主键而不是强加一个唯一约束有何不同?

是的,索引(MySQL实现了一个唯一约束作为索引)会减慢插入速度 同样是主键,这就是为什么表期望高插入负载(IE:用于日志记录)没有定义主键的原因 - 使插入更快。

  

我有很多使用hash和nums列的GROUP BY类型查询。我是否继续添加转换索引,或者我只是添加单个索引?

绝对知道的唯一方法是测试&检查EXPLAIN计划。

更新

根据提供的解释计划,我不认为对第三和第二的关注第4版。 MySQL每个select_type只能使用一个索引。第五个版本可能会受益于覆盖指数。

附录

只是想确保你知道:

ALTER TABLE nt_accs ADD UNIQUE(hash, nums, acc);

...表示三列值的组合将是唯一的。 IE:这些是有效的,唯一约束将允许:

hash  nums  acc
----------------
1     1     1
1     1     2
1     2     1
2     1     1