问题
Although there are many questions on this topic going around, none of the suggestions seem to work. I've got a couple of stored procedures which should be run on a daily basis - some of these stored procedures are quite straight forward, others a bit more tricky. But even the simplest of procedures will run indefinitely when called from a C# program (console) using the SqlClient. This client is running on the server and should be promoted to a windows service when it's actually functioning.
What I've tried so far.
- Add ARITHABORT ON (or OFF) as first execute after connection initialization.
- Add ARITHABORT ON (or OFF) as first command in the Stored Procedure
- Using
WITH RECOMPILE
- Add ARITHABORT as a global configuration thing.
(EXEC sys.sp_configure N'user options', N'64'
GO
RECONFIGURE WITH OVERRIDE
GO
)
The stored procedures (all of them) have no input parameters and the simplest (the only one I currently use) is this:
CREATE PROCEDURE [dbo].[_clean_messageLog]
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;
set arithabort on;
DELETE FROM MessageLog WHERE Moment < GETDATE() - 60;
DELETE FROM MessageLog WHERE Moment < GETDATE() - 30 AND [Status] = 200;
END
There are no messages to be actually deleted and in SSMS the stored procedures executes (as expected) within milliseconds. From the C# Console Application however it takes forever (literally).
Main-method:
const int TIME_OUT = 900000; // 15 minutes
timer.Stop();
foreach (var command in commands.Where(command => !string.IsNullOrWhiteSpace(command)))
{
var start = DateTime.Now;
WriteEvent(string.Format("Starting: {0}", command), EventLogEntryType.Information);
using (var sql = new Lib.Data.SqlServerHelper(connectionString))
{
sql.newCommand(command.Trim());
sql.execute(TIME_OUT);
}
WriteEvent(string.Format("Done in {0} seconds", DateTime.Now.Subtract(start).TotalSeconds), EventLogEntryType.Information);
}
Does anyone have suggestions?
EDIT
The sqlHelper is just a basic (very simple) wrapper. But even when I change the above code to this:
foreach (var command in commands.Where(command => !string.IsNullOrWhiteSpace(command)))
{
var start = DateTime.Now;
WriteEvent(string.Format("Starting: {0}", command), EventLogEntryType.Information);
using (var sql = new SqlConnection(connectionString))
{
sql.Open();
var sqlCommand = new SqlCommand(command.Trim(), sql) {CommandType = CommandType.StoredProcedure};
sqlCommand.ExecuteNonQuery();
}
WriteEvent(string.Format("Done in {0} seconds", DateTime.Now.Subtract(start).TotalSeconds), EventLogEntryType.Information);
}
It's exactly the same.
EDIT #2
Is there an option I can schedule these stored procedures to be run by SQL Server itself on an interval or specific time?
SOLVED
Kinda, although I've never found an actual C# solution to my problem using the SQL Server Agent did the trick. The C# processes were locked due to deadlock issues - which sometimes also occur on the jobs (not as many as the console program), but we're working on that.
回答1:
Is there an option I can schedule these stored procedures to be run by
SQL Server itself on an interval or specific time?
Yes, SQL Server Agent can run jobs based on specific time or interval.
Creating SQL Server Job
SSMS -> SQL Server Agent -> Right-Click -> New Job -> Select Name, Database, Code and Schedule
When you finish you can click Script
button and get script that create job (if needed).
You can also start Job using T-SQL (for example from application/another stored procedure or trigger):
EXEC msdb.dbo.sp_start_job N'JobName';
来源:https://stackoverflow.com/questions/32311130/very-slow-executenonquery-stored-procedure-vs-fast-execution-using-sql-server