在 table 上性能缓慢,只有超过 100 万条记录:索引是否错误?
Slow performance on table with just over 1 million records: Are the indexes wrong?
我被要求调查一个越来越慢的应用程序的性能问题。很快,我就能够将问题缩小到单个数据库 table。结构不良的 C# 代码我可以优化。但是有了 SQL tables,我就不那么自信了。所以我在这里希望得到一些帮助!
有问题的 table 存储应用程序中使用的某些关键字的多语言翻译。这是一个增长 table。随着它的增长,基本 SELECT 和 JOIN 的性能开始急剧下降。现在 table 中的记录刚刚超过 100 万条,实际上还不算多。
例如:
SELECT * FROM PE_TranslationPhrase WHERE Phrase = 'ABC-123'
这可能需要 8 到 32 秒才能完成。
table 托管在 Azure SQL 上。下面是在 SSMS 中查看它:
所以它没有 table 的那么复杂。主键结构不仅仅是普通的自动递增整数。 TranslationId
和 CultureName
一起构成主键(这很好)。
在处理性能问题时,首先要看的当然是索引。这是现在 table 上的内容:
CLUSTERED:
- [TranslationId] ASC,
- [CultureName] ASC
STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF
和
NON-CLUSTERED:
- [CultureName] ASC,
- INCLUDE ([Phrase])
STATISTICS_NORECOMPUTE = OFF, DROP_EXISTING = OFF, ONLINE = OFF
Phrase
和 CultureName
的非聚集索引的原因是因为这些列一直用于过滤器和连接。示例:
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
我尝试过的内容和问题:
我尝试重建索引:
ALTER INDEX ALL ON dbo.PE_TranslationPhrase REBUILD
这似乎对性能没有可衡量的影响。
我的问题是:将 CultureName
作为两个索引的一部分是否不好?
我该如何/应该更改这些索引?
谢谢!!
对于这个查询:
SELECT * FROM PE_TranslationPhrase WHERE Phrase = 'ABC-123'
您需要一个索引,其中 Phrase
是索引中的第一个键。
None 个索引的第一列为 Phrase
,因此数据库需要扫描整个 table.
我被要求调查一个越来越慢的应用程序的性能问题。很快,我就能够将问题缩小到单个数据库 table。结构不良的 C# 代码我可以优化。但是有了 SQL tables,我就不那么自信了。所以我在这里希望得到一些帮助!
有问题的 table 存储应用程序中使用的某些关键字的多语言翻译。这是一个增长 table。随着它的增长,基本 SELECT 和 JOIN 的性能开始急剧下降。现在 table 中的记录刚刚超过 100 万条,实际上还不算多。
例如:
SELECT * FROM PE_TranslationPhrase WHERE Phrase = 'ABC-123'
这可能需要 8 到 32 秒才能完成。
table 托管在 Azure SQL 上。下面是在 SSMS 中查看它:
所以它没有 table 的那么复杂。主键结构不仅仅是普通的自动递增整数。 TranslationId
和 CultureName
一起构成主键(这很好)。
在处理性能问题时,首先要看的当然是索引。这是现在 table 上的内容:
CLUSTERED:
- [TranslationId] ASC,
- [CultureName] ASC
STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF
和
NON-CLUSTERED:
- [CultureName] ASC,
- INCLUDE ([Phrase])
STATISTICS_NORECOMPUTE = OFF, DROP_EXISTING = OFF, ONLINE = OFF
Phrase
和 CultureName
的非聚集索引的原因是因为这些列一直用于过滤器和连接。示例:
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
我尝试过的内容和问题:
我尝试重建索引:
ALTER INDEX ALL ON dbo.PE_TranslationPhrase REBUILD
这似乎对性能没有可衡量的影响。
我的问题是:将 CultureName
作为两个索引的一部分是否不好?
我该如何/应该更改这些索引?
谢谢!!
对于这个查询:
SELECT * FROM PE_TranslationPhrase WHERE Phrase = 'ABC-123'
您需要一个索引,其中 Phrase
是索引中的第一个键。
None 个索引的第一列为 Phrase
,因此数据库需要扫描整个 table.