sql server - Openquery vs 4part name - sql

A view that references a remote server
4part name ([ServerName], [DatabaseName], [Owner], [Object Name]
OpenQuery
Which is better performance?
Why is performance good?

AFAIK, it depends a lot on your remote server type.
With recent SQL version (2016) on both server (local and remote), I didn't noticed any difference.
If your remote server is anything else (postgres, mysql...) your really should use OpenQuery as it executes the query on the remote server, getting only the correct resultset. If you use the 4 part name, SQL server will order and filter on local.
For example, take a 4 million record table and execute a query like :
SELECT * FROM reoteserver.database.schema.table where id = 4
With openquery, sql server will get only the record with id 4. Without, it will get all the table, and then filter it to get the id 4.

Late to the party here, but the difference essentially is that 4 part queries are executed locally, thus cannot utilise indexes or keys since the local server doesn't know about them. Instead it essentially retrieves the entire object, then applies the filter. On a small table, you would be unlikely to notice a difference, but on a table with millions of rows, you'd notice a difference. Openquery essentially tells the remote server to execute the query on it's behalf then pass the result back.
General rule I would say is;
NEVER join on to a table using 4 part. Only join using Openquery and I would even avoid that where possible, but that's more of a personal preference.
However, 4 part SP execution i.e. EXEC ServerName.DBName.SchemaName.ObjectName is essentially the same since that also tells the remote server to execute the query on its behalf.

Related

How to query remote procedure or view

I have 2 server A and Server B(remote 3rd party) both SQL server 2012. We need to query the data from remote Server B, we are planning to use either view or stored procedure. The query contain multiple joins to fetch data from around 10 tables(minimum 10 tables is there in initial analysis may be more tables will be added in future).
If we are going to access the data through VIEW then we are going to write the below query
SELECT * FROM view-name WHERE Column1 ='abc'
My first question
Q1. I have a doubt whether this query will load all the data from table joined in the view and then the WHERE condition implement as in the VIEW definition we are not implementing the filter condition. If it is like that then this will be a performance issue, Please correct me if it is like this or not.
Q2. Which will has better performance a stored procedure or view.
Q3. How to call a remote stored procedure or View. linked server is not allowed.
Does the 4 part server.DB.Schema.SPorView name will work.
I had search and find about OPENROWSET/OPENQUERY does it works without linked server.
Please let me know if need further clarification
Thanks

Single SQL query run against multiple linked SQL servers/DBs

I have a single SQL query that I need to run against ~25 different databases- each residing on a separate SQL server on the network. The query will run from a single central SQL server management studio, and the 24 other SQL server instances are linked. I have the query I need, and I tested that it works- however the goal is to create a script that queries each of the 25 separate SQL instances.
Instead of writing the query out 25 separate times within the script, I'm wondering if there's a way to utilize the single block of code to query each of the linked instances using an array, variables, DO/WHILE, a function or any other method.
Here's the query:
SET NOCOUNT ON
PRINT 'local server';
SELECT isc.ini_schema_name[Device], count(*) [Count]
FROM pharos.dbo.edi_pharos_stations eps, pharos.dbo.ini_schemas isc
WHERE eps.ini_schema_id = isc.ini_schema_id
GROUP BY isc.ini_schema_id, isc.ini_schema_name
For the purpose of this example, if I were to utilize the less-graceful approach of writing out the block of code 24 more times, this would be the next query in the script (to query SQL server hostnamed pharos90-2008).
PRINT 'Pharos90-2008';
SELECT isc.ini_schema_name[Device], count(*) [Count]
FROM [pharos90-2008].pharos.dbo.edi_pharos_stations eps, [pharos90-2008].pharos.dbo.ini_schemas isc
WHERE eps.ini_schema_id = isc.ini_schema_id
GROUP BY isc.ini_schema_id, isc.ini_schema_name
As you can see, the query / code is exactly the same except for the fact that it is referencing a separate linked SQL Server (query being run from a central SQL Server Management Studio).
The ultimate goal is to output the queried data for each SQL instance to a single .txt file; format being, print the name of each particular SQL server followed by the corresponding queried data.
Any advice as to how one would accomplish such a task?
Thanks in advance.
Well, one way would be to create a cursor to iterate all of your linked servers. (You can find linked servers like this...)
SELECT * FROM sys.servers WHERE is_linked = 1
Then, you could use the undocumented sp_MSForEachDB stored procedure to run a dynamic version of your query (changing the server on each iteration) on each database in the cursor's current server. If you search for sp_MSForEachDB you can find plenty of information. But here's one link to save time.

Query SQL Linked Server only pulling data from one server

I have four SQL Servers that are named in the following way:
dbs
dbs2
dbs3
dbs4
I have a table that is on dbs3 called table1 in database1. This table does not exist on the other servers. However when I run the query:
select *
from dbs.database1.dbo.table1 (or any of the database servers)
it returns the results as if I queried the existing table on dbs3. It is like the DBMS is ignoring the 4 part nameing in the query and returning the results from table on dbs3 no matter which server I try to designate in the 4 part naming convention. Any ideas what could be going on here. The servers appear in the linked servers list.
If you can make changes without breaking stuff (or if it's already broken enough in your opinion), I recommend recreating your linked servers. If your linked server is another SQL Server, you can do
exec sp_dropserver 'dbs';
exec sp_addlinkedserver 'dbs';
This creates a linked server definition with the default configuration, which is appropriate for most applications (and can still be tweaked afterwards).

Results returned from a view using linked server may vary?

i have a view that is using linked server to retrieve data from a remote server in SQL Server. On each time viewing the view, the results returned are vary. For example, 1st time execution may return 100 rows of records but on 2nd time of execution, rows returned are 120 rows. Any ideas what is the cause?
I have witnessed odd linked-server results that are a product of non-determinism written into the SQL itself, I.e. a TOP query written without an ORDER BY clause.
This problem, for example, where the chap had multiple non-unique foreign keys coming from a table source on the left hand side of a linked-server INNER JOIN, and wanted 10 rows from a remote sub-query to the right, where the end result was restricted to 10 rows itself, when it should have been greater than 10 rows.
Should definitely give your SQL a quick eye for such curiosities.
The data on the linked server changed between executions?
Is your SQL Server fully patched? SQL Server 2008 and 2005 both have bug fixes out related to incorrect query results from linked servers.
Here is one example:
969997 FIX: You receive an incorrect result when you query data from a linked server that is created by using an index OLE DB provider in SQL Server 2005 or in SQL Server 2008
Is the linked server also a SQL Server? If not, perhaps a buggy driver? I've seen odd results, for example, due to an old Informix ODBC driver. Are you able to run something akin to SQL Profiler on the linked server to see what command it's receiving?
I'm not sure what the answer is, but (assuming that your counts of 100 and 120 are accurate) can you not capture the data from the two runs and compare it? That might give you some clues as to what's going on. For example, is it completely different datat, or is it duplicate rows (in the 120 row batch).

Openquery works much faster than a query straight to a linked table

Trying to figure out why there is such a significant difference between
select * from linkedserver..tablename
and
select * from openquery(linkedserver, select * from tablename).
4 minutes vs 13 seconds.
OPENQUERY connects to the destination server and runs the query on that server and returns the resultset. Whereas, I believe the Linked Server query is executed on the local server and runs across the connection.
Hope this helps.
Openquery connects directly to the destination server. Despite saying the RDBMS, you did not said what the other way to communicate with the data was.
Do you know if it is trying to enlist a distributed transaction over the linked server? If you watch the Trace output from Oracle when the calls are made, you should be able to see the difference in the requests happening. IIRC, the standard link query will request schema information from the oracle metadata in a different manner than the OPENQUERY call does. I don't know exactly why this happens, but I had a similar issue in the past that was resolved by using OPENQUERY.