Замедляет ли добавление уникального ограничения? - PullRequest
6 голосов
/ 05 октября 2010

В моей таблице три столбца.

+-----------+-----------------------+------+-----+---------+-------+
| 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);

У меня есть около 500 миллионов строк для вставки в эту таблицу, и эта таблица имеетбыл разделен с помощью RANGE на числа примерно на 20 разделов.

  1. Замедляет ли уникальное ограничение вставки?Чем это отличается от простого создания первичного ключа вместо наложения уникального ограничения?
  2. У меня много запросов типа GROUP BY с использованием столбцов hash и nums.Можно ли добавить конвертирующий индекс или просто добавить отдельные индексы?

РЕДАКТИРОВАТЬ:

Объяснить планпосле разбиения и вставки некоторых тестовых данных

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 Ответ

8 голосов
/ 05 октября 2010

Замедляет ли уникальное ограничение вставки? Чем это отличается от простого создания первичного ключа вместо наложения уникального ограничения?

Да, индекс (MySQL реализует уникальное ограничение в качестве индекса) замедлит вставки.
То же самое относится и к первичному ключу, поэтому в таблицах, ожидающих высокую загрузку при вставке (т.е. для ведения журнала), не определен первичный ключ - для ускорения вставок.

У меня много запросов типа GROUP BY с использованием столбцов hash и nums. Нужно ли мне добавлять конвертирующий индекс или просто добавить отдельные индексы?

Единственный способ точно знать, это проверить и проверить план EXPLAIN.

UPDATE

В свете предоставленных планов объяснения, я не вижу проблем для 3-й и 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
...