When SQL Server 2005 was released, a nifty little feature was included called synonyms. Despite being around since SQL Server 2005, I think this feature is often under-utilized or, more importantly, it is implemented in a very bad way.
Today I want to share a couple of examples. We will take a look at examples of both good and bad implementations of synonyms.
First, let’s take a look at the syntax for creating a synonym. Per BOL (and for the fun of it, here is the 2005 link).
-- SQL Server Syntax
CREATE SYNONYM [ schema_name_1. ] synonym_name FOR <object>
<object> :: =
{
[ server_name.[ database_name ] . [ schema_name_2 ]. OBJECT_NAME
| database_name . [ schema_name_2 ].| schema_name_2. ] OBJECT_NAME
}
-- Windows Azure SQL Database Syntax
CREATE SYNONYM [ schema_name_1. ] synonym_name FOR < OBJECT >
< OBJECT > :: =
{
[database_name. [ schema_name_2 ].| schema_name_2. ] OBJECT_NAME
}
So a sample implementation of a Synonym could be something like the following.
CREATE SYNONYM [syn].[Staging_Cardumum] FOR [Cardamum_UAT].[dbo].[cardamum_staging]
GO
Before we delve into that sample synonym, lets look at an example of a really bad implementation.
The BAD
While working with a client, I received a request to look into why a linked server query was failing. (This isn’t necessarily the bad, just hang in there for a bit.) The message was something like this:
The OLE DB provider “SQLNCLI10” for linked server “blahblahblah” indicates that either the object has no columns or the current user does not have permissions on that object.
The error message seems at least semi-descriptive and gives a starting point. In this case, I decided to verify the linked server was created properly, verified that the permissions were done properly and even tested the linked server. On the source (linked) and destination server (let’s call the Source server ServerA and the Destination server we will call ServerB), I verified that permissions were in place for each database to be touched. Still no dice!
Well, let’s go take a look and see if that referenced table actually exists. It did not! Does it exist as a view? It did not! Alas, the table existed as a synonym. This is where it gets wonky. In looking at the definition of the synonym, I found that the table defined in the synonym had a linked server table as its source. To top things off, the linked server was back on the originating server that was coming across the link in the first place. So yes, that would be ServerB initiated a query against ServerA to pull data back to ServerB. But the data needed (as defined by the vendor) was available on ServerA – supposedly. Reality had that data actually sitting on ServerB the whole time.
At any rate, thanks to having a synonym for each and every table sitting on ServerA that referenced a table across a linked server on ServerB, we had mass confusion. In the end, the query was far simpler to execute by just pulling it from the originating query server (ServerB).
This implementation of a synonym was not the best. All it did was cause confusion, create documentation inaccuracies and delay the developer from accomplishing her task. Do you really need 1000s of synonyms in your database? Do you need all of them going across a linked server? If you do, did you ever think about the potential for performance issues? (The vendor in this case used those linked servers and synonyms to perform a data conversion that took 36 hrs each time for a rather small dataset – ouch!!!!).
On the other Hand
Imagine, if you will, two databases sitting on the same box. One database will be for your user data, and the other for “staging” data for processes such as those related to ETL. Imagine further that, for some inane reason, the naming standard of your databases must include the suffix denoting the environment of the database.
Now picture an SSIS package that must utilize tables from both databases in data sources somehow. At least one of the tables has millions of records. And both of the tables have nearly 100 columns. Even just pulling in the minimum amount of data using a query from each source can cause memory issues. Two separate data sources means you will likely have a sort transformation (for each source) as well as a join transformation.
Trying to reduce the amount of data in the larger table source could be done via TSQL. But to reference a database in one environment versus another environment means a code change with each deployment (due to the TSQL – think three part naming). So you have been hampered by the environment. Or have you?
By using a synonym in this situation, the data can be joined in a tsql data source by referencing that synonym. Let’s look back at the sample synonym posted earlier in this article.
CREATE SYNONYM [syn].[Staging_Cardumum] FOR [Cardamum_UAT].[dbo].[cardamum_staging]
GO
You can see that this synonym follows the same sort of naming standards as was just laid out in the preceding scenario. If I create a synonym in each environment by the same name, and referencing the appropriate environment named database, I have just opened up a performance tweak for my SSIS datasource.
By implementing this slight tweak, I have been able to gain a 10x performance improvement in package performance. I am now requiring SSIS to ingest fewer records and thus chew up less memory. Fewer transformations are required and the package can just fly into the required transformations, rather than tinkering around with the transformations needed to just get the data into a usable state for those transformations.
There are other benefits within SSIS to using synonyms for databases on the same server as well. Especially when dealing with this kind of naming standard that requires the databases to be named differently in each environment.
Conclusion
How you use a synonym can be a huge asset or it can be a significant dampener to performance. There are benefits and uses for these nifty little things. Check them out and let us know how you have been able to put synonyms to use to benefit you.