Oracle performance - disabling FKs to make DELETE statement work faster? - sql

When deleting from a large table in Oracle - let's call it table X - does it make sense to disable table X's FKs that do not have ON DELETE CASCADE? I'm not referring to disabling FKs on other tables that link to table X, but just disabling FKs on table X to improve the performance of the DELETE statements.
I'm making the indexes on table X unusable, but the DELETE still takes a while.
I think that those FKs don't matter to the performance of the DELETE statement since we're just deleting, and not inserting or updating, so the FKs don't need to be checked. What do you think?

That seems like a really bad idea. No matter what you do, you'll have a period where referential integrity is not enforced on your database. Then you go to put the FKs back in place and, oops, someone has inserted an invalid row.
Furthermore, ALTER TABLE is a DDL statement, so executing it will commit any work up to that point. You'll lose the ability to rollback if something goes wrong elsewhere in your transaction.
Can you look through the explain plan to see why your DELETE statement is taking so long?

Eventually I didn't have to disable those FKs before the archive process starts and enable them when the process ends. But instead, in order to improve performance of the DELETE statements, we had to drop indexes before the archive process starts and recreate them after the archive process finishes. We also committed more often.

Related

What are differences between, and best purposes of, DROP, TRUNCATE, and DELETE? Can they be rolled back? [duplicate]

This question already has answers here:
What's the difference between TRUNCATE and DELETE in SQL
(32 answers)
Closed 9 years ago.
*Delete is a DML(Data Manipulation Language). Delete command deletes records from the existing table.*The syntax for Delete is
sql> Delete from .
This Deletes All the Record From The TAble
sql> Delete from
Where **
This deletes a particular set of records.
Note:Delete is not Autocommit Statement(In fact none of the DML are auto commit)
Drop and Truncate both are DDL(Data Definition Language).
Drop {Delete or drops} the table with it's structure. It is autocommit statement. Drops Once fired can not be rolled back.
syntax:
sql>drop table
Truncate is the command used to delete all record from table. but the structure of the table remain same.It is also a autocommit statement.
syntax;
sql>truncate table**
Can we rollback the truncate?
DELETE handles rows chosen with a WHERE statement. Its use is part of the discipline of running production applications. For example, you might DELETE all rows that have been marked "complete" more than a month ago.
DELETE can be done as part of a transaction. That is, DELETE operations can be committed or rolled back.
TRUNCATE rapidly removes all rows from a table while maintaining the table definition. (Row by row DELETE can take time, especially for tables with lots of keys.) It comes in handy for such things as log tables that start out empty for each week's production. It has the convenient side effect of resetting the indexes and releasing unused disk storage. I have used TRUNCATE to wipe out the contents of a log table that used to contain millions of rows, to switch to an operational discipline where it only contains a weeks' worth of rows, for example.
DROP rapidly removes all rows and the table's definition. It's used most often in connection with setting up a DBMS schema for operations or migrating data to a new server.
TRUNCATE and DROP are considered data definition statements. As such they can't be part of transactions, and can't be rolled back.
If you find yourself using TRUNCATE or DROP in routine production, you should be careful to understand why you're doing so. They are blunt instruments compared to DELETE.
The DELETE command is used to remove rows from a table. A WHERE clause can be used to only remove some rows.
TRUNCATE removes all rows from a table. The operation cannot be rolled back and no triggers will be fired.
The DROP command removes a table from the database. All the tables' rows, indexes and privileges will also be removed. No DML triggers will be fired.
Check this out,
"Drop" removes the table completely. It no longer exists.
"Truncate" is a fast way of removing all the rows from the table.
"Delete" removes rows that match a condition.
see also: What's the difference between TRUNCATE and DELETE in SQL

How Do I Ignore Errors When Deleting Records

I'm in the process of testing a large number of schema changes to upgrade our db to run with the latest version of a packaged product we have.
At this point I'm not interested in the data contained in the db, only the schema (i.e. the tables, views, constraints, keys, stored procedures, etc.).
My testing entails running scripts, resolving errors, an re-running the scripts. If I want to re-run the scripts I need to first restore the db to get it back to a known state. Restoring the db is very time consuming as it has lots of data. I would like to "slim down" the db and remove as much data as possible. That way it will be quicker to restore the db and re-run my scripts
When I attempt to delete records from many of the tables ("delete from table-name") I run into constraint errors and the command stops.
Is there a way to allow the command to continue and, in effect, delete all the records in the table where there aren't constraint issues? In other words I'd like the command to ignore errors and continue to delete all the records it can.
Any Suggestions would be greatly appreciated.
Byron above makes a good point; you can disable FOREIGN KEY or CHECK constraints with the ALTER TABLE command:
ALTER TABLE TableName NOCHECK CONSTRAINT ALL
Then do your work, and when finished,
ALTER TABLE TableName CHECK CONSTRAINT ALL
to re-enable constraints. Be careful, though: if you leave your data in an inconsistent state that violates constraints once you re-enable them, future updates can fail due to constraint errors.
Sources:
http://weblogs.sqlteam.com/joew/archive/2008/10/01/60719.aspx
http://technet.microsoft.com/en-us/library/ms190273.aspx

Add an identity column to existing table which is changing always

I have an existing table with 15 million rows in it. I want to add an identity column and make it primary key. The problem is this table is always moving (inserts, updates, deletes). Is it possible to add the identity column with this? Or I have to stop the backgroud processes (it is a tedious task) which updates this table?
Thanks
Vikram
Given that you have 15 million rows it might take some non-trivial amount of time to execute the ALTER TABLE statement.
Since SQL Server doesn't provide table hints for ALTER TABLE its pretty safe to assume that SQL Server takes a table lock when it executes an ALTER TABLE statement.
During this time no other process will be allowed to Select, insert, update, or delete so you don't have to worry about a race condition with some other process.
If the process takes long enough your other processes will experience timeout errors. Depending on how the processes are written this is either a bad thing or a non-issue, but you'll need to figure that out. If it were me I would turn them off.

deleting a large number of rows from a table

We have a requirement to delete rows in the order of millions from multiple tables as a batch job (note that we are not deleting all the rows, we are deleting based on a timestamp stored in an indexed column). Obviously a normal DELETE takes forever (because of logging, referential constraint checking etc.). I know in the LUW world, we have ALTER TABLE NOT LOGGED INITIALLY but I can't seem to find the an equivalent SQL statement for DB2 v8 z/OS. Any one has any ideas on how to do this really fast? Also, any ideas on how to avoid the referential checks when deleting the rows? Please let me know.
In the past I have solved this kind of problem by exporting the data and re-loading it with a replace style command. For example:
EXPORT to myfile.ixf OF ixf
SELECT *
FROM my_table
WHERE last_modified < CURRENT TIMESTAMP - 30 DAYS;
Then you can LOAD it back in, replacing the old stuff.
LOAD FROM myfile.ixf OF ixf
REPLACE INTO my_table
NONRECOVERABLE INDEXING MODE INCREMENTAL;
I'm not sure whether this will be faster or not for you (probably it depends on whether you're deleting more than you're keeping).
Do the foreign keys already have indexes as well?
How do you have your delete action set? CASCADE, NULL, NO ACTION
Use SET INTEGRITY to temporarily disable constraints on the batch process.
http://www.ibm.com/developerworks/data/library/techarticle/dm-0401melnyk/index.html
http://publib.boulder.ibm.com/infocenter/db2luw/v8/index.jsp?topic=/com.ibm.db2.udb.doc/admin/r
We modified the tablespace so the lock would occur at the tablespace level instead of at the page level. Once we changed that DB2 only required one lock to do the DELETE and we didn't have any issues with locking. As for the logging, we just asked the customer to be aware of the amount of logging required (as there did not seem to be a solution to get around the logging issue). As for the constraints, we just dropped and recreated them after the delete.
Thanks all for your help.

Bulk delete (truncate vs delete)

We have a table with a 150+ million records. We need to clear/delete all rows. Delete operation would take forever due to it writing to the t-logs and we cannot change our recovery model for the whole DB. We have tested the truncate table option.
What we realized that truncate deallocates pages from the table, and if I am not wrong makes them available for reuse but doesn't shrink the db automatically. So, if we want to reduce the DB size, we really would need to do run the shrink db command after truncating the table.
Is this normal procedure? Anything we need to be careful or aware about, or are there any better alternatives?
truncate is what you're looking for. If you need to slim down the db afterwards, run a shrink.
This MSDN refernce (if you're talking T-SQL) compares the behind the scenes of deleting rows versus truncating.
"Delete all rows"... wouldn't DROP TABLE (and re-recreate an empty one with same schema / indices) be preferable ? (I personally like "fresh starts" ;-) )
This said TRUNCATE TABLE is quite OK too, and yes, DBCC SHRINKFILE may be required afterwards if you wish to recover the space.
Depending on the size of the full database, the shrink may take a while; I've found it to go faster if it is shrunk in smaller chunks, rather than trying to get it back all at once.
One thing to remember with Truncate Table (as well as drop table) is going forward this will not work if you ever have foreign keys referencing the table.
As pointed out, if you can't use truncate or drop
SELECT 1
WHILE ##ROWCOUNT <> 0
DELETE TOP (100000) MyTable
You have a normal solution (truncate + shrink db) to remove all the records from a table.
As Irwin pointed out. The TRUNCATE command won't work while being referenced by a Foreign key constraint. So first drop the constraints, truncate the table and recreate the constraints.
If your concerned about performance and this is a regular routine for your system. You might want to look into moving this table to it's own data file, then run shrink only against the target datafile!