I have an odd situation. We have an AS400 with a Prod side and a Dev side (same machine, 2 nic cards) From a production SQL Server, we run a query from a MS-SQL server that is using a linked Server, I'll call 'as400' The query does 3 joins, and the execution plan looks roughly like [Remote Query] => Got Results. It does the joins on the remote server (the Production AS400) This will execute in no more than 0:00:02 (2 seconds) One of the joined tables has 391 MILLION rows. It is pulling 100 rows - joined to the other table.
Now, it gets weird. On the Dev side of the same machine, running on a different SQL Server, coming in the other NIC card, executing the same query with a different database (the dev one) the execution plan is quite different! It is:
[Query 1] hash match (inner join) with [Query2] Hash with [Query3] Hash with [Query4]
Expecting that each query returns 10,000 rows (I'm sure it is just using that as a guess as it doesn't know the actual rows as it is remote). What it appears to be doing is pulling 391 million rows back on query2 and it takes > 23 HOURS before I give up and kill the query. (Running in SSMS)
Clearly, the MS SQL Server is making the decision to not pass this off to the AS400 as a single query. Why?
I can 'solve' the problem by using a OpenQuery (as400, cmd) instead, but then it will open us up to SQL Injection, can't do simple syntax checking on the query, and other things I don't like. It takes 6 seconds to do the query using OpenQuery, and returns the correct data.
If we solve this by rewriting all our (working, fast) queries that we use in production so they can also run against dev - it involves a LOT of effort and there is down-side to it in actual production.
I tried using the 'remote' hint on the join, but that isn't supported by the AS400 :-(
Tried looking at the configuration/versions of the SQL Servers and that didn't seem to offer a clue either. (SQL Servers are nearly the same version/are same, 10.50.6000 for the one that works, and 10.50.6220 for one that fails (newer), and also 10.50.6000 for the other one that is failing.)
Any clues anyone? Would like to figure this out, we have had several people looking at this for a couple of weeks - including the Database Architect and the IBM AS400 guru, and me. (So far, my OpenQuery is the only thing that has worked)
One other point, the MS Servers seem to be opening connections 5 per second to the AS400 from the machines that are not working (while the query runs for 23 hours) - I don't understand that, and I'm not 100% sure it is related to this issue, but it was brought up by the AS400 guy.
I despise linked servers for this reason (among many others). I have always had good luck with openquery() and using sp_executesql to help prevent SQL injection.
There is mention of this here: including parameters in OPENQUERY
Without seeing the queries and execution plans it sounds like this is a problem with permissions when accessing statistics on the remote server. For the query engine to make use of all available statistics and build a plan properly, make sure the db user that is used to connect to the linked server is one of the following on the linked server:
The owner of the table(s).
A member of the sysadmin fixed SERVER role.
A member of the db_owner fixed DATABASE role.
A member of the db_ddladmin fixed DATABASE role.
To check what db user you're using to connect to the linked server use Object Explorer...
Expand the Server\Instance > Server Objects > Linked Servers > right click your linked server and select properties, then go to the Security page.
If you're not mapping logins in the top section (which I wouldn't suggest) then select the last radio button at the bottom to make connections using a specific security context and enter the username and password for the appropriate db user. Rather than using 'sa' create a new db user on the linked server that is #2 or #3 from above and use that. Then every time the linked server is used it will connect with the necessary permissions.
Check the below article for more detail. Hope this helps!
http://www.benjaminnevarez.com/2011/05/optimizer-statistics-on-linked-servers/
Related
I have admin account,
I need a query to run everyday.
This query is heavy and cannot run on production server.
"selecting" is takes 30 mins.
So I need to use azure readonly secondary node.
When It runs on secondary node It doesnt lock production server.
after the select, output needs to be inserted to a table.
Table is in prod but just stored for reports.
This is not risky.
I can do that in C# with 2 connection strings, but I want to do it in SQL server.
Is it possible to select from [secondary node] and write to production server ?
You should be able to accomplish that using 4 part name and that is using a Linked Server
Pushing data using linked server would be ok but if you have lots of data to move between servers then pulling it will work better (save the data to a db not participating in Availability Group and execute a procedure on the remote (your Primary Replica) server that pulls the desired data).
Regardless of the above the fact the query takes so long to complete indicates there may be room for improvement, or possibly a missing index.
I have two Windwos Server 2012 connected with 1Gbps switch. They are in blade and sharing same storage.
When I copy files between them I am geting the speed of 982Mbps. So that is great ;)
Also I have two SQL Server 2012 installed on those machines and those servers are linked to each other, with TCP, (not named pipes).
And connection between them is, slow. I have created one large table ~ 2GB without indexes ..
I have tried with indexed table also, every query is ~ 3 times slower when linked server is involved.
I have tried to execute bunch of small ones that only selects one row realy fast, and they are also 3 times slower.
No metter what I do, ethernet speed is always ~120Mbps
And when I execute from SQL SERVER A:
select * into SQL_SERVER_A.NEWTABLE from
SQL_SERVER_A.TABLE
It takes about 1min;
select * into SQL_SERVER_A.TABLE from LINKED_SERVER_SQLB.DATABASE.SCHEMA.TABLE
I need about 2:30
So my guess was, maybe HDD cannot optimaze how to read/write since it is on different server.
But when I execute also from SQL SERVER A, also about 2:30
select * into LINKED_SERVER_SQLB.SCHEMA.NEWTABLE from LINKED_SERVER_SQLB.DATABASE.SCHEMA.TABLE
So I am inserting into same database. But time is different. So my guess is it is network issue. Speed newer goes above 120Mbps.
I have tried tracert and I get other machine in one hoop.
Is this network issue?
How can I investigate further?
I have tried with OPENQUERY results are the same.
Execution plan:
Running SQL Server 2014 Express on our domain. We use Windows Authentication to log on. All queries are performed in stored procedures.
Now, the system runs fine for all our users - except one. When he logs on (using our software), all queries take around 10 times longer (e.g. 30 ms instead of 2 ms). The queries are identical, the database is the same, the network speed is the same, the operative system is the same, the SQL Server drivers are the same, connection pooling is the same, DNS is the same. Changing computer does not help. The problem seems to be linked to the account being used.
What on Earth may be the cause for this huge performance hit?
Please advise!
I would try rebuilding the SP (by running an ALTER statement that duplicates its existing structure) to force SQL Server to recompile. I don't know every way SQL Server caches things but it can definitely create distinct execution plans for different types of connections so I wouldn't be surprised if your slow user is running a version with an inefficient execution plan.
http://www.sommarskog.se/query-plan-mysteries.html
I have a big data table for store articles(has more than 500 million record), therefore I use distributed partition view feature of SQL Server 2008 across 3 servers.
Select and Insert operations work fine. But Delete or Update action take long time and never complete.
In Processes tab of Activity Monitor, I see Wait Type field is "PREEMPTIVE_OLEDBOPS" for Update command.
Any idea what's the problem?
Note: I think problem with MSDTC, because Update command not shown in SQL Profiler of second server. but when check MSDTC status on the same server, status column is Update(active).
What is most likely happening is that all the data from the other server is pulled over to the machine where the query is running before the filter of your update statement is applied. This can happen when you use 4-part naming. Possible solutions are:
Make sure each table has a correct "check constraint" which defines the minimum and maximum value of the partition table. Without this partition elimination is not going to work properly.
Call a stored procedure with 4-part naming on the other server to do the update.
use OPENQUERY() to connect to the other server
To serve 500 million records your server seems to be adequate. A setup with Table Partitioning with a sliding window is probably a more cost effective way of handling the volume.
I am trying to optimize some stored procedures on a SQL Server 2000 database and when I try to use SQL Profiler I get an error message "In order to run a trace against SQL Server you have to be a member of sysadmin fixed server role.". It seems that only members of the sysadmin role can run traces on the server (something that was fixed in SQL Server 2005) and there is no way in hell that I will be granted that server role (company policies)
What I'm doing now is inserting the current time minus the time the procedure started at various stages of the code but I find this very tedious
I was also thinking of replicating the database to a local installation of SQL Server but the stored procedure is using data from many different databases that i will spend a lot of time copying data locally
So I was wondering if there is some other way of profiling SQL code? (Third party tools, different practices, something else )
Your hands are kind of tied without profiler.
You can, however, start with tuning your existing queries using Query Analyzer or
any query tool and examining the execution plans. With QA, you can use
the Show Execution Plan option. From other tools you can use the
SET STATISTICS PROFILE ON / OFF
In query analyser:
SET STATISTICS TIME ON
SET STATISTICS IO ON
Run query and look in the messages tab.
It occurs to me this may require same privileges, but worth a try.
There is a workaround on SQL 2000 to obfuscate the Profiler connection dialogue box to limit the sysadmin connection to running traces only.
SQLTeam
Blog