СУБД
Добавил(а) shixaro, последний раз редактировал(а) shixaro Mar 09, 2010  (посмотреть изменения)
Метки: 

Задача, простая на первый взгляд, и вызывающая затруднения у неискушенных.
Пример: у нас есть таблица с четырьмя полями

mysql> create table t (t1 integer, t2 integer, t3 integer, t4 integer);
Query OK, 0 rows affected (0.15 sec)

mysql> desc t;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| t1    | int(11) | YES  |     | NULL    |       |
| t2    | int(11) | YES  |     | NULL    |       |
| t3    | int(11) | YES  |     | 0       |       |
| t4    | int(11) | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
4 rows in set (0.00 sec)

Пусть она будет заполнена какими-то данными:

mysql> select * from t;
+------+------+------+------+
| t1   | t2   | t3   | t4   |
+------+------+------+------+
|    1 |    2 |    3 |    4 |
|   11 |   22 |   33 |   44 |
|  111 |  222 |  333 |  444 |
+------+------+------+------+
3 rows in set (0.00 sec)

Нам стало нужно поменять местами столбцы t3 и t4:

mysql> ALTER TABLE t MODIFY COLUMN t3 integer AFTER t4;
Query OK, 3 rows affected (0.11 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from t;
+------+------+------+------+
| t1   | t2   | t4   | t3   |
+------+------+------+------+
|    1 |    2 |    4 |    3 |
|   11 |   22 |   44 |   33 |
|  111 |  222 |  444 |  333 |
+------+------+------+------+
3 rows in set (0.00 sec)

Готово.

Пример перестановки столбцов в таблице с миллионом записей.
1. Заполняем таблицу:

# time for i in `seq 1 1000000`; do echo 1$i\;2$i\;3$i\;4$i >> /tmp/test.txt; done

real    0m33.456s
user    0m25.654s
sys     0m6.156s

# time mysql test -e "LOAD DATA INFILE '/tmp/t.txt' INTO TABLE t FIELDS TERMINATED BY ';'"

real    0m0.556s
user    0m0.004s
sys     0m0.004s

mysql> select count(*) from t;
+----------+
| count(*) |
+----------+
|  1000001 |
+----------+

Это наиболее быстрый способ нагрузить тестовую таблицу. Можно сделать это и группой вставок:

for i in `seq 1 1000000`; do echo mysql test -e \""insert into t values ('1$i', '2$i', '3$i', '4$i')"\" | sh; done

Но операция будет длиться значительно дольше, т.к. на вставку каждой строки расходуется один запрос против одного в изначальном примере.

2. Меняем столбцы местами (с замером времени):

# time mysql test -e "ALTER TABLE t MODIFY COLUMN t2 integer AFTER t3"

real    0m0.652s
user    0m0.000s
sys     0m0.004s

Как видно, операция заняла меньше секунды.

Также были проведены тесты с таблицей в ~14млн и ~140млн записей. Затраченное время в формате мм:сс, соответственно, 00:52 и 3:01. Согласно нагруженности системы данные показатели могут "плавать", но суть не в этом. Очевидна связь между размером таблицы и затраченным временем и это показывает, что столбцы перемещаются на носителе физически, а не просто проводится замена информации в заголовках (в этом случае затрачивалось бы примерно одно и то же время на таблицу любых размеров).

Операции проводились под ОС Linux. Во FreeBSD этот кусок

seq 1 1000000

должен быть заменен на:

seq2 -s 1 -e 1000000

Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.5 Build:#805 Apr 26, 2007) - Запрос Bug/feature - Связаться с администраторами