Huge oracle insert statement gets stuck - c#

I'm trying to add data from multiple XML files into my Oracle database. I'm receiving the data in my .NET C# application and I'm using Dapper as ORM.
Currently there are 13 XML files which need to be added into the database. I deserialized all of them and turned them into an INSERT query to add to my database.
Everything seems to be working fine, except after 31 minutes of trying to insert the data in the database, I noticed the following error:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout
expired
After some searching I found this solution: https://stackoverflow.com/a/11895078/2664414 but this seems way to hacky for something this "simple".
As for the details of the INSERT statement, I'm adding 3271 rows for the second INSERT. Here is a short snippet:
INSERT ALL
INTO S1589_XML_LineSection (ID, VALID_FROM_DATE, VALID_TO_DATE, LINE_ID, CHANNEL_NO, TENSION, NATURE, P70, C70, P400, C400, OPERATIONAL_IMPORTANCE, TECHNICAL_EQUIPMENT, OPERATIONALISATION, STANDARD_SPEED_DIR_1, STANDARD_SPEED_DIR_2, LAST_UPDATE_DATE) VALUES ('1','1996-06-02','2005-12-10','404','0','1','1','0','0','330','330','9','9','1','0','0','2010-06-04T04:54:51')
INTO S1589_XML_LineSection (ID, VALID_FROM_DATE, VALID_TO_DATE, LINE_ID, CHANNEL_NO, TENSION, NATURE, P70, C70, P400, C400, OPERATIONAL_IMPORTANCE, TECHNICAL_EQUIPMENT, OPERATIONALISATION, STANDARD_SPEED_DIR_1, STANDARD_SPEED_DIR_2, LAST_UPDATE_DATE) VALUES ('1','2005-12-11','2007-12-08','404','0','1','1','0','0','330','330','9','9','1','60','60','2010-06-04T04:54:51')
SELECT 1 FROM dual
I can perfectly add these lines individually, but when I try to add them all at once, it takes way too long.
So, tips on either improving the query, or making sure I don't get the error (ORA-00054)?

Related

Can I execute IF statements from an external source?

I have a data table, and each row contains a set of about 77 values, these values I need to run through about 1200 IF statements, but the IF statements (rules) may vary.
My original idea was to have a SQL table, with columns memberName, operator, target, trueValue, falseValue. Read the data from the table and in run time create expressions and run the data through that. And the idea worked well, the IF statements just seems to be more complicated than just "IF age > 30".
Read more at: How can I calculate an expression parameter in run time?
So I thought, IF I can have an external file, that can be switched after the application has been installed, send the data table to the method(?) in the file and the file returns a single result value. That would also work perfect.
Can I do this with a .dll file maybe? Or something similar.
So to summarize, I want to run my data table values, through IF statements that I get from an external source because the IF statements might change from time to time.

Getting inserted record from DataSet TableAdapter.Insert

I'm using a DataSet with the DataSet designer on xsd file (System.Data v 4 in VS 2015). I've been searching for how to get the ID for a newly created record. I see on the designer advanced options there is an option for reading back the record for insert and updates. I also see the SELECT included in the INSERT INTO statement. However the designer generated code runs ExecuteNonQuery and returns the number of records affected. How do we get access to that record that was read back in?
Most solutions I've read involve creating your own query or sp that is set to ExecuteScalar and selects the ##ROWIDENTITY. Either that or timestamp the new record and get it back that way. But if the read-back is already being done then I should be able to get to it, right? What' the trick? What happens to that data that's been read back in?
TIA,
Mike

How to query an SQLite db in batches

I am using C# with .NET 4.5. I am making a scraper which collects specific data. Each time a value is scraped, I need to make sure it hasn't already been added to the SQLite db.
To do this, I am making a call each time a value is scraped to query against the db to check if it contains the value, and if not, I make another call to insert the value into the db.
Since I am scraping multiple values per second, this gets to be very IO-intensive, with constant calls to the db.
My question is, is there any better way to do this? Perhaps I could queue the values scraped and then run a batch query at once? Is that possible?
I see three approaches:
Use INSERT OR IGNORE, which will reject an entry if it is already present (based on primary key and unique fields). Or plainly INSERT (or its equivalent (INSERT or ABORT) which will return SQLITE_CONSTRAINT, a value you will have to catch and manage if you want to count failed insertions.
Accumulate, outside the database, the updates you want to make. When you have accumulated enough/all, start a transaction (BEGIN;), do your insertions (you can use INSERT OR IGNORE here as well), commit the transaction (COMMIT;)
You could pre-fetch a list of items you already have, depending, and check against that list, if your data model allows it.

Bulk Insert into access database from c#?

How can I do this. I have about 10000 records in an an Excel file and I want to insert all records as fast as possible into an access database?
Any suggestions?
What you can do is something like this:
Dim AccessConn As New System.Data.OleDb.OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\Test Files\db1 XP.mdb")
AccessConn.Open()
Dim AccessCommand As New System.Data.OleDb.OleDbCommand("SELECT * INTO [ReportFile] FROM [Text;DATABASE=C:\Documents and Settings\...\My Documents\My Database\Text].[ReportFile.txt]", AccessConn)
AccessCommand.ExecuteNonQuery()
AccessConn.Close()
Switch off the indexing on the affected tables before starting the load and then rebuilding the indexes from scratch after the bulk load has finished. Rebuilding the indexes from scratch is faster than trying to keep them up to date while loading large amount of data into a table.
If you choose to insert row by row, then maybe want to you consider using transactions. Like, open transaction, insert 1000 records, commit transaction. This should work fine.
Use the default data import features in Access. If that does not suit your needs and you want to use C#, use standard ADO.NET and simply write record-for-record. 10K records should not take too long.

Minimise database updates from changes in DataTable/SqlDataAdapter

My goal is to maximise performance. The basics of the scenario are:
I read some data from SQL Server 2005 into a DataTable (1000 records x 10 columns)
I do some processing in .NET of the data, all records have at least 1 field changed in the DataTable, but potentially all 10 fields could be changed
I also add some new records in to the DataTable
I do a SqlDataAdapter.Update(myDataTable.GetChanges()) to persist the updates (an inserts) back to the db using a InsertCommand and UpdateCommand I defined at the start
Assume table being updated contains 10s of millions of records
This is fine. However, if a row has changed in the DataTable then ALL columns for that record are updated in the database even if only 1 out of 9 columns has actually changed value. This means unnecessary work, particularly if indexes are involved. I don't believe SQL Server optimises this scenario?
I think, if I was able to only update the columns that had actually changed for any given record, that I should see a noticeable performance improvement (esp. as cumulatively I will be dealing with millions of rows).
I found this article: http://netcode.ru/dotnet/?lang=&katID=30&skatID=253&artID=6635
But don't like the idea of doing multiple UPDATEs within the sproc.
Short of creating individual UPDATE statements for each changed DataRow and then firing them in somehow in a batch, I'm looking for other people's experiences/suggestions.
(Please assume I can't use triggers)
Thanks in advance
Edit: Any way to get SqlDataAdapter to send UPDATE statements specific to each changed DataRow (only to update the actual changed columns in that row) rather than giving a general .UpdateCommand that updates all columns?
Isn't it possible to implement your own IDataAdapter where you implement this functionality ?
Offcourse, the DataAdapter only fires the correct SqlCommand, which is determined by the RowState of each DataRow.
So, this means that you would have to generate the SQL command that has to be executed for each situation ...
But, I wonder if it is worth the effort. How much performance will you gain ?
I think that - if it is really necessary - I would disable all my indexes and constraints, do the update using the regular SqlDataAdapter, and afterwards enable the indexes and constraints.
you might try is do create an XML of your changed dataset, pass it as a parameter ot a sproc and the do a single update by using sql nodes() function to translate the xml into a tabular form.
you should never try to update a clustered index. if you do it's time to rethink your db schema.
I would VERY much suggest that you do this with a stored procedure.
Lets say that you have 10 million records you have to update. And lets say that each record has 100 bytes (for 10 columns this could be too small, but lets be conservative). This amounts to cca 100 MB of data that must be transferred from database (network traffic), stored in memory and than returned to database in form of UPDATE or INSERT that are much more verbose for transfer to database.
I expect that SP would perform much better.
Than again you could divide you work into smaller SP (that are called from main SP) that would update just the necessary fields and that way gain additional performance.
Disabling indexes/constraints is also an option.
EDIT:
Another thing you must consider is potential number of different update statements. In case of 10 fields per row any field could stay the same or change. So if you construct your UPDATE statement to reflect this you could potentially get 10^2 = 1024 different UPDATE statements and any of those must be parsed by SQL Server, execution plan calculated and parsed statement stored in some area. There is a price to do this.

Categories

Resources