我们需要以不同语言显示我们的产品名称,但只有部分产品的名称与英语不同。当我们使用特定语言查询产品时,如果缺少某个语言名称,我们希望以英语显示默认名称。
为了获得更好的查询性能,我们必须在缺少特定语言的名称时将默认英文名称填充到语言相关的产品名称表(languageid + productid是主键)。它在这个语言相关表中创建了大量重复的名称,当更改默认英文名称时更新此表有点困难。
目前,我们在此表中有大约300,000种产品,大约30种语言和超过8,000,000行,至少90%以上的数据是重复的,并填写默认的英文名称。但是如果我们在查询中使用left join和isnull check,则查询性能会慢得多。
谁可以向我推荐一个更好的数据库设计,我可以避免填写重复数据并获得更好的查询性能?
当前表架构如下
Table1 (about 300,000 rows)
ProductId | Country | Currency | others fields
------------|----------------|-----------|---------------
Product A | US | USD | ...
Product B | GB | GBP | ...
Table2 (about 9,000,000 rows)
LanguageId | ProductId | Product Name
------------|----------------|--------------------------
English | Product A | Product A Name
English | Product B | Product B Name
German | Product A | Produkt A Name
German | Product B | Product B Name (it's filled by English name)
我尝试过以下查询以避免重复数据,但性能有点差。
SELECT
A.ProductId,
A.Country,
ISNULL(B1.ProductName, B2.ProductName) as ProductName
FROM
Table1 A (NOLOCK)
LEFT JOIN Table2 B1 (NOLOCK) on A.ProductId = B1.ProductId
LEFT JOIN Table2 B2 (NOLOCK) on A.ProductId = B2.ProductId and B2.LanguageId = 'ENGLISH'
WHERE
B1.LanguageId = 'German'
ORDER BY
ISNULL(B1.ProductName, B2.ProductName)
答案 0 :(得分:2)
您是否测试过LEFT JOIN和ISNULL?或者这只是猜测?鉴于你正在转移大量数据,我会说可选语言行会快得多,除非你有一些非常糟糕的索引
SELECT
...,
ISNULL(L.languageproductName, P.productname)
FROM
Product P
LEFT JOIN
LangaugeStuff L ON P.productID = L.productID AND L.languageID = @Mylanguage
答案 1 :(得分:1)
我不确定这是否适用于您的特定情况,但为什么不让UI界面层或应用层通过常见的本地化模式处理翻译呢?
答案 2 :(得分:0)
如果该语言记录中没有您的产品名称,请在该字段中添加NULL
。在您进行查询时,请使用COALESCE
将NULL
替换为您的英文产品名称。
SELECT COALESCE(l.ProductName, 'Product Name')
FROM Language l
我提议的设计看起来像这样:
Language | ProductName | TitleMenu
----------------------------------
English | Widgetizer | Title
French | La Widgette | La Title
Spanish | | El Title
由于西班牙语有一个NULL
条目,COALESCE
会跳过null并输入默认的产品名称。