I've been asked to look into a performance issue for an app that is becoming progressively slower. Pretty quickly, I was able to narrow down the problem to a single database table. Poorly structured C# code I'm ok at optimizing. But with SQL tables, I'm less confident. So I'm here hoping for some help!
The table in question stores multi-lingual translations for certain keywords used across the app. It's a growth table. And as it grows, the performance on basic SELECTs and JOINs is starting to degrade sharply. Right now there are just over 1 million records in the table, which isn't really all that much.
For example:
SELECT * FROM PE_TranslationPhrase WHERE Phrase = 'ABC-123'
That can take anywhere from 8 to 32 seconds to complete.
The table is hosted on Azure SQL. Here's a look at it in SSMS:
So it's not that complex of a table. The Primary Key structure isn't just your normal auto-incremented integer. TranslationId
and CultureName
together make up the primary key (which is fine).
When dealing with performance issues, the first place to look, of course, is the indexes. This is what's on the table now:
CLUSTERED:
- [TranslationId] ASC,
- [CultureName] ASC
STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF
And
NON-CLUSTERED:
- [CultureName] ASC,
- INCLUDE ([Phrase])
STATISTICS_NORECOMPUTE = OFF, DROP_EXISTING = OFF, ONLINE = OFF
The reason for the NON-CLUSTERED index with Phrase
and CultureName
is because those columns are used all the time for filters and joins. Example:
LEFT JOIN
PE_TranslationPhrase TP
ON A.Description COLLATE Latin1_General_CS_AS = TP.Phrase COLLATE Latin1_General_CS_AS
AND A.CULTURENAME = TP.CultureName
WHAT I'VE TRIED, AND QUESTIONS:
I tried to rebuild the indexes:
ALTER INDEX ALL ON dbo.PE_TranslationPhrase REBUILD
That didn't seem to have a measurable impact on performance.
My question is: Is it bad to have CultureName
as part of both indexes?
How could I / should I change these indexes?
Thanks!!
For this query:
SELECT * FROM PE_TranslationPhrase WHERE Phrase = 'ABC-123'
You want an index where Phrase
is the first key in the index.
None of your indexes have Phrase
as the first column, so the database needs to scan the entire table.