I have this largish table with three columns as such:
+-----+-----+----------+ | id1 | id2 | associd | +-----+-----+----------+ | 1 | 38 | 73157604 | | 1 | 112 | 73157605 | | 1 | 113 | 73157606 | | 1 | 198 | 31936810 | | 1 | 391 | 73157607 | +-----+-----+----------+
This continues for 38m rows. The problem is I want to remove the 'associd' column but running ALTER TABLE table_name DROP COLUMN associd;
simply takes too long. I wanted to do something like: ALTER TABLE table_name SET UNUSED associd;
and ALTER TABLE table_name DROP UNUSED COLUMNS CHECKPOINT 250;
then which apparently speeds up the process but it isn't possible in MySQL?
Is there an alternative to remove this column-- maybe creating a new table with only the two columns or getting a drop with checkpoints?
SQL allows a user to remove one or more columns from a given table in the database if they are no longer needed or become redundant. To do so, the user must have ALTER permission on the object.
Right-click the column you want to delete and choose Delete Column from the shortcut menu. If the column participates in a relationship (FOREIGN KEY or PRIMARY KEY), a message prompts you to confirm the deletion of the selected columns and their relationships. Choose Yes.
To physically drop a column you can use one of the following syntaxes, depending on whether you wish to drop a single or multiple columns. alter table table_name drop column column_name; alter table table_name drop (column_name1, column_name2);
“If you are concerned about the length of time it could take to drop column data from all of the rows in a large table, you can use the ALTER TABLE...SET UNUSED statement.
Anything that you do is going to require reading and writing 38m rows, so nothing is going to be real fast. Probably the fastest method is probably to put the data into a new table:
create table newTable as select id1, id2 from oldTable;
Or, if you want to be sure that you preserve types and indexes:
create table newTable like oldTable; alter table newTable drop column assocId; insert into newTable(id1, id2) select id1, id2 from oldTable;
However, it is usually faster to drop all index on a table before loading a bunch of data and then recreate the indexes afterwards.
Disclaimer: this answer is MySQL oriented and might not work for other databases.
I think in the accepted answer there are some things missing, I have tried to expose here a generic sequence I use to do this kind of operations in a production environment, not only for adding/removing columns but also to add indexes for example.
We call it the Indiana Jones' movement.
A new table using the old one as template:
create table my_table_new like my_table;
In the new table:
alter table my_table_new drop column column_to_delete;
The are not generate automatically in the create table like
command.
You can check the actual foreign keys:
mysql> show create table my_table;
Then apply them to the new table:
alter table my_table_new add constraint my_table_fk_1 foreign key (field_1) references other_table_1 (id), add constraint my_table_fk_2 foreign key (field_2) references other_table_2 (id)
Copy all fields but the one you want to delete.
I use a where
sentence to be able to run this command many times if necessary.
As I suppose this is a production environment the my_table
will have new records continuously so we have to keep synchronizing until we are capable to do the name changing.
Also I have added a limit
because if the table is too big and the indexes are too heavy making a one-shot clone can shut down the performance of your database. Plus, if in the middle of the process you want to cancel the operation it will must to rollback all the already done insertions which means your database won't be recovered instantly (https://dba.stackexchange.com/questions/5654/internal-reason-for-killing-process-taking-up-long-time-in-mysql)
insert my_table_new select field_1, field_2, field_3 from my_table where id > ifnull((select max(id) from my_table_new), 0) limit 100000;
As I was doing this several times I created a procedure: https://gist.github.com/fguillen/5abe87f922912709cd8b8a8a44553fe7
Be sure you run this commands inmediately after you have replicate the last records from your table. Idealy run all commands at once.
rename table my_table to my_table_3; rename table my_table_new to my_table;
Be sure you have a back up before you do this ;)
drop table my_table_3
Disclaimer: I am not sure what will happen with foreign keys that were pointing to the old table.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With