Conditionally delete SQL rows - linq

Using Linq 2 SQL CE on Windows Phone 7.1, how can I trigger "DELETE FROM table_name WHERE some_column=some_value" SQL command?
Unfortunately, erasing items with Table.DeleteAllOnSubmit() method is unacceptably slow even after increasing "max buffer size" parameter to 1024: stupud Linq deserializes each record, so the DataContext.SubmitChanges() method never returns.

You cannot trigger the desired DELETE statement, but you can do:
Use .Take(100) to only fetech and delete a set of records per SubmitChanges() call, and run in a loop until you get no more rows returned.
Use a rowversion column to speed up deletes, from 320 ms to under 70 ms in my test - see http://erikej.blogspot.dk/2012/04/windows-phone-local-database-tip.html

Related

Oracle 19: Why IN gets converted to Exist in explain plan and any suggestions around it

Please see image below:
As per that the IN query got converted to Exists in explain plan. Any reason for that? does it mean Oracle automatically converts IN to Exists?
Also any suggestion to reduce the cost? this statement is a part of a SP and it receives ~ separated string ('123') for example (63278~63282~63285~63288~63291~63296~63299~63302~63305~63308~63311~63314~63319~63322~63325~63329~63332~63253~63256~63260~63264~63267~63272~63275~63279~63283~63286~63289~63292~63297~63300~63303~63306~63309~63312~63315~63320~63323~63326~63330~63333~63269~63258~63277~63294~63317~63262~63270~63281~63295~63318~63328~63254~63257~63261~63265~63268~63273~63276~63280~63284~63287~63290~63293~63298~63301~63304~63307~63310~63313~63316~63321~63324~63327~63331~63334) in query. It takes around 10 to 15 mins to execute.
How can we generate explain plan for entire stored proc? We are using Oracle 19.
Thank you in advance.
IN clause retrieves all records which match with the given set of values. It acts as multiple OR conditions. IN clause scans all rows fetched from the inner query.
But, EXISTS is a Boolean operator that returns either True or False. Its used in combination to a sub-query. If the subquery returns any row, it returns True else False. If the result of data large inside the IN clause, then not recommended using IN. For getting high performance most time uses EXISTS vs IN. For that Oracle and PostgreSQL converts your IN to EXISTS
Since you are doing the job in a PL/SQL procedure you could create (out of the procedure) a GLOBAL TEMPORARY TABLE with DELETE ON COMMIT, in the procedure you INSERT in this table the result of the sub select with the CONNECT BY, then your replace the SELECT ... CONNECT BY by a SELECT in the temporary table. The temp table will be emptied at the end of the procedure and this method is session safe. And you have benefit of the index and probably a better plan. You could also compare the UPDATE with 2 ones: splitting the OR condition on 2 statements.

Stored Procedure does not use available index on table (Oracle)

A SELECT query in my stored procedure takes 3 seconds to execute when the table queried has no indexes. This is true in both when executing the query in Toad Editor and when calling the stored procedure. The Explain Plan shows that a full table scan is done.
When an index is added, the same query in Toad Editor returns results instantaneously (just a few milliseconds). The Explain Plan shows that the index is used. However, even when the index is present, the query still takes 3 seconds in the stored procedure. It looks like the query uses a full table scan when executed in stored procedure despite having an index that can speed it up. Why?
I have tried with indexes on different columns with different orders. The same results persist in all cases.
In the stored procedure, the results of the query are collected using BULK COLLECT INTO. Does this make a difference? Also, The stored procedure is inside a package.
The query is a very simple SELECT statement, like this:
SELECT MY_COL, COUNT (MY_COL)
/* this line is only in stored proc */ BULK COLLECT INTO mycollection
FROM MY_TABLE
WHERE ANOTHER_COL = '123' /* or ANOTHER_COL = filterval (which is type NUMBER) */
GROUP BY MY_COL
ORDER BY MY_COL
Without source code we can only guess...
So I suspect it's because in Toad you get just first 500 rows (500 is default buffer size in Toad) but in stored proc you fetch ALL rows into collection. So fetching probably takes most of 3 sec time. Especially if there are nested loops iny our query.
Update: It might also be implicit type conversion in where condition

Using CFQUERY and Returning a Recordset Using an Oracle Anonymous Block

Reference: Oracle SQL RETURN INTO Fails within CFQUERY (ORA-06550/PLS-00103)
Placing the PL/SQL into a variable then executing in a CFQUERY tag works, but when I dump the query variable, I get "Variable XX is undefined".
How do I get the anonymous block to return the id of the affected record, or better yet, the entire record?
Below is the code which executes, but throws the error...
<cfset plsql = "
DECLARE record_id scpricequeue.scpricequeueid%TYPE;
BEGIN
update scpricequeue
set datelocked = sysdate
where scpricequeueid = (
select scpricequeueid
from (
select scpricequeueid
from scpricequeue
where islocked = 0 and completed = 0
order by dateadded asc
)
where rownum <= 1
)
RETURNING scpricequeueid INTO record_id;
END;
">
<cfset sql = "
select *
from scpricequeue
">
<cfquery name="q" datasource="ecomd">
#plsql#
</cfquery>
<cfdump var="#q#">
ERROR: Variable q is undefined
I solved my specific need in another way, by using SELECT ... FOR UPDATE
When you issue a SELECT statement against the database to query some records, no locks are placed on the selected rows. In general, this is a wonderful feature because the number of records locked at any given time is kept to the absolute minimum: only those records that have been changed but not yet committed are locked. Even then, others are able to read those records as they appeared before the change (the “before image” of the data).
There are times, however, when you will want to lock a set of records even before you change them in your program. Oracle offers the FOR UPDATE clause of the SELECT statement to perform this locking.
When you issue a SELECT...FOR UPDATE statement, the database automatically obtains row-level locks on all the rows identified by the SELECT statement, holding the records “for your changes only” as you move through the rows retrieved by the cursor. It’s as if you’ve issued an UPDATE statement against the rows, but you haven’t—you’ve merely SELECTed them. No one else will be able to change any of these records until you perform a ROLLBACK or a COMMIT—but other sessions can still read the data.
Ref: Oracle PL-SQL by O’Reilly, Pg 492
However, I was also tracking down a couple other more complex but promising solutions. I never reached conclusion, but in the hopes that these are useful pointers for others, here they are.
Oracle Package/CF Stored Procedure: See section titled “Use Oracle referenced cursors to return result sets (ColdFusion 4.5+, Oracle 7.3+):” and “Oracle PL-SQL” (Chapter 18 on Packages). I just hadn't figured out how to create the package and link it to CF, but this seemed like it would definitely be a viable solution.
I was going to test to see if CFTRANSACTION puts a lock on a record, which would be similar to my SELECT...FOR UPDATE solution above.

SQL Performance - SSIS takes 2 mins to call a SProc, but SSMS takes <1 sec

I have an SSIS package that fills a SQL Server 2008 R2 DataWarehouse, and when it recreates the DW from scratch, it does several million calls to a stored procedure that does the heavy lifting in terms of calculations.
The problem is that the SSIS package takes days to run and shouldn't take that long. The key seems to be that when the SSIS package calls the SProc, it takes about 2 minutes for the SProc to return the results. But if I recreate the call manually (on the same database) it takes <1 sec to return the result, which is what I'd expect.
See this screen shot, in the top is the SQL Profiler Trace showing the call by the SSIS Package taking 130 seconds, and in the bottom is my recreation of the call, taking <1 sec.
http://screencast.com/t/ygsGcdBV
The SProc queries the database, iterates through the results with a cursor, does a lot of calculations on pairs of records, and amalgamates the numbers into 2 results which get returned.
However the timing of the manual call, suggests to me that it's not an issue with the SProc itself, or any indexing issue with the database itself, so why would the SSIS package be taking so much longer than a manual call?
Any hints appreciated.
Thanks,
I don't have a solution for you, but I do have a suggestion and a procedure that can help you get more information for a solution.
Suggestion: a stored proc that gets called millions of times should not be using a cursor. Usually a cursor can be replaced by a few statements and a temp table or two. For temp tables with more than 10k rows or so, index it.
Procedure: At key places in your stored proc put a statement
declare #timer1 datetime = GetDate()
(some code)
declare #timer2 datetime = GetDate()
(more code)
declare #timer3 datetime = GetDate()
then, at the end:
select
datediff(ss,#timer1,#timer2) as Action1,
datediff(ss,#timer2,#timer3) as Action2
At that point, you'll know which part of your query is working differently. I'm guessing you've got an "Aha!" coming.
I suspect the real problem is in your stored procedure, but I've included some basic SSIS items as well to try to fix your problem:
Ensure connection managers for OLE DB sources are all set toDelayValidation ( = True).
Ensure that ValidateExternalMetadata is set to false
DefaultBufferMaxRows and DefaultBufferSize to correspond to the table's row sizes
DROP and Recreate your destination component is SSIS
Ensure in your stored procedure that SET ANSI_NULLS ON
Ensure that the SQL in your sproc hits an index
Add the query hint OPTION (FAST 10000) - This hint means that it will choose a query which will optimise for the first 10,000 rows – the default SSIS buffer size
Review your stored procedure SQL Server parameter sniffing.
Slow way:
create procedure GetOrderForCustomers(#CustID varchar(20))
as
begin
select * from orders
where customerid = #CustID
end
Fast way:
create procedure GetOrderForCustomersWithoutPS(#CustID varchar(20))
as
begin
declare #LocCustID varchar(20)
set #LocCustID = #CustID
select * from orders
where customerid = #LocCustID
end
It could be quite simple. Verify the indexes in the table. It could be similiar/conflicting indexes and the solution could be to drop one of them.
With the SQL query in SSMS have a look at the Execution plan and which index object is used. Is it the same for the slow SP?
If they use different indexes try to use the fast one in SP. Example how to:
SELECT *
FROM MyTable WITH (INDEX(IndexName))
WHERE MyIndexedColumn = 0

Oracle ref cursor fetch hangs if it contains 1 single record

I have a weird problem right now that if a ref cursor returned from a stored procedure that has only 1 record in it, the fetch operation will hang and freeze. The stored procedure execution was really fast, just the fetching process hangs. If the ref cursor has more than 1 record, then everything is fine. Does anyone have similar issues before?
The Oracle server is 11g running on Linus. The client is Windows Server 2003. I'm testing this using the generic Oracle sqlplus tool on the Windows Server.
Any help and comments would be greatly appreciated. thanks.
When you say hangs, what do you mean ?
If the session is still active in the database (status in V$SESSION), then it is probably waiting on some event (eg SQL*Net from client means it is waiting for the client to do something).
It may be that the query is taking a long time to find that there aren't any more rows. Consider a table of 10,000,000 rows with no indexes. The query may full scan the table and find the first row matches the criteria. It still has to scan the next 9,999,999 rows to find that they don't. That can take a while.
Since you are saying that the process hangs, Is there a chance that your cursor does a "select for Update" instead of "Select " ? Since you are saying that the fetch of multiple records does not cause this error, that might not be the case.
Can you show us the code (or a reproducible small test/sample) for your select and the fetch.
Also, you can check the v$locked_objects using the following query and giving in your table name(s) to see if the object in question is being locked. Again, unless your current query has "for update" this fetch should not hang.
select do.*
from v$locked_objects vo,
dba_objects do
where vo.object_id = do.object_id
and vo.object_name = '<your_table_name>'

Resources