I insert into this table small amount of data just about 1000 rows and it takes more than 4 minutes
Remote data modifications through a linked server use the sp_cursor
model. The effect is similar to issuing 1000 separate single inserts (one for each row). If a round trip takes 250ms, 1000 such trips will take 4 minutes and 10 seconds. Using a bulk loading method such as bcp
or SSIS
will generally be more efficient (unless the number of rows to be inserted is tiny).
Another alternative for ad-hoc needs is to build a string containing a single INSERT
statement with multiple rows in the VALUES
clause. The statement is then used with EXECUTE AT
, for example:
-- Note local-to-azure table name used, not four-part syntax
DECLARE @sql varchar(max) = 'INSERT dbo.Test VALUES ';
-- Build a list of 1000 numbers to insert
SELECT @sql += '(' + CONVERT(varchar(11), n) + '),'
FROM dbo.Numbers AS N
WHERE n BETWEEN 1 AND 1000;
-- Remove trailing comma
SET @sql = LEFT(@sql, LEN(@sql) - 1);
-- For debugging
PRINT @sql;
-- Execute the finished statement at the remote server;
EXECUTE (@sql) AT AZURE;
The constructed insert statement executes at the Azure database, so a local name is used for the table (note: building a dynamic insert statement using a four-part target name buys you nothing).
Note that EXECUTE ... AT
requires RPC
and RPC OUT
enabled in the linked server options.
The VALUES
clause for a plan INSERT
statement is limited to 1000 elements. There are ways around that (a VALUES
clause in a CTE does not have that restriction). You could also choose to build 1000-row batches or build single-row insert statements, but if the there is that much data on a regular basis, you would probably be better off using one of the bulk loading methods instead.
This is not definitive proof but just my opinion based on what I learned from a PluralSight course Paul Randal did on wait stats.
PREMEPTIVE
waits are indicative that SQL Server Operating System (SQLOS) has to change a thread to preemptive mode to handle something outside of SQL Server, at the OS level.
Now as you have already determined this types of waits are not documented much at all. There are a few you can see documented in BOL under the sys.dm_os_wait_stats
DMV but it is not extensive. In most cases the calls being made to the OS are via Windows API calls. So what I ended up learning from the course is that if you take off the PREMEPTIVE
portion of the PREEMPTIVE_REENLIST
you end up with the name of the possible API being used: REENLIST
. So if you take that and start searching around on the web you can try and deduce what it means.
So my deducing would be that I came across this MSDN article on IResrouceManager::Reenlist
there are also other MSDN articles on similar named methods that all discuss a TransactionManager
. It is not the content that catches my eye but the section of MSDN where this article is located: DTC Interfaces. So you don't specify this level of setup for your server but I would make a hunch that you are using distributed transactions. This can come from making remote calls to other instances/databases or if you are working on a clustered instance. If you actually read a statement from the MS DTC Service, although it is from SQL Server 2000 you might catch the key word that caught my eye:
One or more servers running SQL Server can then be instructed to enlist in the distributed transaction and coordinate the proper completion of the transaction with MS DTC
Just my opinion...
Best Answer
Confirm the trace is actually gathering those columns. The following query will show the events and columns being captured for each trace (except the default system trace):
The results look something like this (depending on the events and columns you've defined for your trace):