SQL Server : query using synonym in remote server - sql-server

We just migrated our database environment from server 1 to server 2.
We are in SQL Server 2014 (old and new servers).
In the previous environment, we had a DATABASE_1 with a Table_a (in which there is an clustered index) and a DATABASE_2 that contains a synonym_a referencing the DATABASE_1.dbo.table_a. The query using this synonym (SELECT with JOIN) was running fine (select top 10000 in 1s).
Now, we have one server with DATABASE_1 with the Table_a, and another server (linked server) with DATABASE_2 with synonym_a.
The same query is running very slow. I can see the execution plan is different between the 2 environment. The index in table_a is not used in the new environment.
We tried to add WITH INDEX but it is not possible to specify an index hint for a remote data source. We need the synonym (because the same code is deployed automatically in different site and can't have the name of server/database in the code of our queries, stored procedure). And we can't replace the view by a stored procedure.
Does anyone have a solution for this problem?

when you use link server execute plan couldn't see the index of another server that you have link.So when use query by join server A send the request to another server by itself plan and ignore the index by the way
try the chance by use this query
select * from (
select * from Table_a order by (column that index in server 2)
)a inner join (
select * from server2.db.owner.table_b order by column)b
on a.id=b.fkid

Related

How to Use OpenQuery to do Create Alias (IBM DB2) in SQL Server

I use linked server to connect AS400 DB2.
For example: select query can work
select *
from openquery([DB2], 'select t1.* from lib.table01 t1
fetch first 1 rows only')
But I want to use query
Create Alias Library.T_temp For Library.T1 (MemberName)
in SQL Server.
It returned an error because it have no return rows.
As following (it will return error):
Select * from OpenQuery([DB2],' Create Alias...')
Update OpenQuery([DB2],' Create Alias...')
Is there any method to do that?
Thanks
Don't try..
Your openquery() is the preferred solution.
By using openquery(), the SQL statement is passed to Db2 and run there. Since you've included a fetch first 1 rows only only 1 row is returned.
the query form
select TOP 1 t1.*
from db2.myibmi.lib.table01 t1
offset 0 rows
first first 1 row only
Will actually pull back all rows to SQL Server, then filter them on the SQL Server.
(At least I know that's how it used when a WHERE clause was included. I assume TOP isn't any better)

OPENDATASOURCE (Transact-SQL) - Connecting to multiple tables

I have a use case for OPENDATASROUCE. However, my SQL query has multiple tables with left joins.
Most of the examples have one table only. How I connect in case I have 2 tables (2nd table has left join)
Below is a typical example and working great:
SELECT *
FROM OPENDATASOURCE('SQLNCLI', 'Data Source=RemoteServerName;Integrated Security=SSPI').Billing.dbo.Invoices
But I need to join invoices table with 'customer' table like below. I am not sure how I do that?? Please help
SELECT *
FROM OPENDATASOURCE('SQLNCLI', 'Data Source=RemoteServerName;Integrated Security=SSPI').Billing.dbo.Invoices as inv
left join Billing.dbo.customers as cust
on inv.customer = cust.customer
OPENDATASOURCE is one way to talk to a remote server using the "linked server" or "distributed query" functionality in SQL Server. However, it is not likely the best path for you to use in this case as it does not allow for the SQL Server Query Optimizer to rewrite the query and push parts of the query down to the remote source (potentially reducing the number of rows returned to you over a slower network connection vs. your local database). If possible, creating an actual linked server would help you here. This would give you the option to say to the optimizer "these two tables are from the same remote source". Then the optimizer can consider plans that remotes a single query to the remote server that joins those two tables together, applies any filters and group by clauses, and then returns the result to the calling server.
Here's the mechanism to add a linked server:
https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-addlinkedserver-transact-sql?view=sql-server-2017
Once you have a remote server (which I'll call "remote" here), you can write the query using the 4-part name syntax for remote servers instead of using OPENDATASOURCE.
SELECT * FROM REMOTE.Billing.DBO.Invoices LEFT JOIN REMOTE.Billing.DBO.Invoices on <join condition> <WHERE clause>
Here is a paper on how linked servers work under the covers which should give you a conceptual overview as to why this approach is likely better for you:
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.59.8007
Best of luck!

IBM i (AS400) to SQL Server table join syntax

I am using Excel Connection to query customer contracts from DB2 for IBM i (AS400) through SQL Server connection and trying to join a SQL Server table to determine contract expiration date and sales team responsibility.
The AS400 query operates but I continue to receive an error on joining the SQL Server table ACCOUNT.dbo.CUSTOMER but can't find reference to alternate syntax on the join.
[select *
from openquery(
bpcsrpt_new,'
select s.SCID, s.SVER, s.CONTEXP, a.ACCTNAME, a.SALESTEAM
from AS400table1.contract c, AS400table1.subcontract s, ACCOUNT.dbo.CUSTOMER a
where c.cid=''Active''
and c.cid=s.scid
and c.cver=s.sver
and c.cid=a.acid')]
That's not going to work. When you use openquery, the statement gets sent to the remote machine. Obviously, ACCOUNT.dbo.CUSTOMER is not on the remote IBM i (aka AS400) machine.
You could use 4 part naming in the query directly
select s.SCID, s.SVER, s.CONTEXP, a.ACCTNAME, a.SALESTEAM
from IBMILNKNAM.IBMIDBNAM.IBMILIBNAM.contract c
, IBMILNKNAM.IBMIDBNAM.IBMILIBNAM.subcontract s
, ACCOUNT.dbo.CUSTOMER a
where c.cid='Active'
and c.cid=s.scid
and c.cver=s.sver
and c.cid=a.acid
Note however, the SQL Server will pull back the complete contract and subcontract tables to do the join locally.
Openquery is a better option if you're only interested in a few rows of a large table on the IBM i. If I recall correctly, something like so: (not tested)
select *
from (select * from Openquery(IBMIKNKNAM, 'select s.SCID, s.SVER, s.CONTEXP
from contract c
join subcontract s
on c.cid=s.scid
and c.cver=s.sver
where c.cid=''Active'')) as rmt
join ACCOUNT.dbo.CUSTOMER a on a.acid = rmt.cid

Why is a Teradata query faster in MS-Access than SQL Server

I need to join a Teradata table with about 0.5 billion records and a local table with about 10,000 records. I have it working in MS Access and it takes about 15 minutes to run. I would prefer to do it in SQL Server but can't even get a join with 1 record in the local SQL table to work.
Why is MS Access able to do this, albeit slowly, whereas SQL Server chokes? What is MS Access doing differently from SQL Server?
The SQL Server query with a join that fails:
SELECT a.trk, a.wgt
FROM openquery(TERADATA, 'SELECT trk, wgt
FROM SHIPMENT_DB.pkg') a
INNER JOIN (Local_Tbl) b ON a.trk = b.Tracking_Number
A simple SQL Server query without a join that works:
SELECT *
FROM openquery(TERADATA,'SELECT trk, wgt
FROM SHIPMENT_DB.pkg
WHERE trk = ''773423067500''')
Not the answer, but I had a similar issue using OPENDATASOURCE. Performance was terrible, the query took hours to run.
The solution was to ensure all colmns involved in the WHERE clause had mathcing datatypes. In my case the remote column was INT but in the query it was being passed as a varchar: ...'WHERE remote_table.ID = ''4'''...
Once I changed all values to the appropriate datatypes the query took seconds to run.
Look at the Execution Plan in SQL Server. Since it knows very little about the dataset that is going to come back from Teradata, it is making some has assumptions.
Swapping the order of the tables in the join will help. Using an explicit INNER HASH JOIN may help (once you've switched the order).

How to make a select query for sql and access databases?

Using SQL server 2000 and Access 2003
Access Database Name - History.mdb
Access Table Name - Events
SQL Database Name - Star.mdf
SQL Table Name - Person
I want to take the field from person table, and include in Events table by using inner join
Tried Query
Select * from Events inner join person where events.id = person.id
So How to make a query for access and sql databases.
I want to make a Select query in access only. Not an sql Database.
Need Query Help?
While you can (possible, should -- why?) use a linked table, there are as ever more than one way to skin a cat. Here's another approach: put the connection details into the query test e.g. something like
SELECT *
FROM [ODBC;Driver={SQL Server};SERVER=MyServer;DATABASE=Star;UID=MyUsername;Pwd=MyPassword;].Person AS P1
INNER JOIN
[MS Access;DATABASE=C:\History;].[Events] AS E1
ON S1.seq = S2.seq
WHERE E1.id = P1.id;
You can set up a linked table in Access to your SQL Server, and the instructions on how to do so vary slightly in Access versions. Look in the help file for "Linked Table", or go here if you have Access 2007.
Once you have a linked table set up, you'll be able to access the SQL Server table in your query. Note that optimizing a linked table join takes some work.
You can create a linked table in Access, that points to the table in SQL. The rest you can achieve in the query designer.
You should add the msaccess db as a remote server.
then you can do that join

Resources