多言語ユーザーインターフェイスの背後にあるデータベース


8

この質問は、これらの古い質問ですでに対処されている問題よりも少し複雑な問題に関するもので、すべてが互いに重複しています。

多言語のデータベース構造の提案(2011年6月)

多言語データを保持するのに最適なデータベース構造は何ですか?(2010年2月)

多言語データベース設計のベストプラクティスは何ですか?(2009年5月)

多言語データベースのスキーマ(2008年11月)


多言語ユーザーインターフェイスをサポートする最も一般的なデータベーススキームは、すべての言語のすべての翻訳テキストを、テキストID、言語コード、およびテキスト自体の3つの列を持つ1つのテーブルに格納することです。テキストIDと言語コードが一緒になって主キーを構成します。

これで問題ありませんが、ここで複雑さを考えてみましょう。テキストが検索可能である必要があるとします。たとえば、これが多言語のeショップであるとします。つまり、データベースに入力されたすべての製品カテゴリについて、ショップの所有者は、サポートされているN言語のそれぞれに製品カテゴリの名前を入力し、買い物客は名前で製品カテゴリを検索できます。母国語で

問題があります:照合順序

言語によって照合順序は異なり、ある言語で機能する照合順序は別の言語では機能しません。それで、すべての言語のすべてのテキストが1つの列にある場合、どのような照合順序になりますか?特定のテキストのテキストIDを見つけるために、データベースにどのようにクエリするのでしょうか。Web製品では、検索の正確さとパフォーマンスはそれほど重要ではないかもしれませんが、この説明では、それらが本当に重要であると仮定します。

ほとんどのデータベース管理者は、「データベースの照合」という意味で照合の概念に精通しています。幸い、これは単なるデフォルトの照合であり、他の照合情報が存在しない場合に使用されますが、照合を指定できる場所が他にもあります。

  • SQL CREATE INDEXコマンドは、照合指定をサポートしています。(Microsoft SQL Serverがサポートしていないという噂はありますが、それについて誰か知っていますか?)

  • SQL SELECTステートメントも照合をサポートしますが、この場合、照合仕様は関数として機能し、インデックスルックアップの代わりにインデックススキャンを引き起こします。これは、パフォーマンスが必要な場合は許容できない可能性があります。(それでも、それが私たちが持つことができる最高の場合、何もないよりはましかもしれません。)

  • また、Microsoft SQL Serverでは、照合を指定してフィルター処理されたインデックスを作成できる非永続的な計算列を使用できると聞いていますが、これは聞いたことがなく、Microsoft-SQL-Serverのみの場合は機能については、それがどれほどクールでよく考えられていても、使用を控えたいと思います。

では、これらすべてを踏まえて、更新可能で検索可能な多言語データベースが目標である場合、データベースをどのように構成し、クエリをどのように実行するのでしょうか。


この質問は、ここで行われた議論に触発されました。nvarchar(max)がデータベースにデータを格納する方法は、一部のデータが4000文字未満の場合、どのように高速になるでしょうか。


2
マイクロソフト製品のみの機能が本当にクールでよく考えられている場合は、他のベンダーによる同様の製品のサポートを間に合うように得る可能性がかなり高いはずです。ちょっとした考え。

回答:


8

可能使用して、同じ列に異なる照合順序を持つ文字列を格納するためにSQL_VARIANTを

CREATE TABLE dbo.Localized
(
    text_id     INTEGER NOT NULL,
    lang_id     INTEGER NOT NULL,
    text_body   SQL_VARIANT NOT NULL,

    CONSTRAINT [PK dbo.Localized text_id, lang_id]
        PRIMARY KEY CLUSTERED (text_id, lang_id),
)
GO
INSERT dbo.Localized
    (text_id, lang_id, text_body)
VALUES
    (1001, 2057, N'Database problems' COLLATE Latin1_General_CI_AS);
GO
INSERT dbo.Localized
    (text_id, lang_id, text_body)
VALUES
    (1001, 1025, N'قاعدة بيانات المشاكل' COLLATE Arabic_CI_AS)

この設計には、特に検索領域にいくつかの欠点があります(8000バイトに制限されていることを含む)。SQL_VARIANTフルテキストインデックスを作成できず、一部の文字列比較機能(などLIKE)も直接使用できません。一方、照合に対応した方法で通常のインデックスを作成し、より基本的な比較(<、=、>など)を実行することできますSQL_VARIANT

CREATE UNIQUE INDEX uq1 ON dbo.Localized (text_body)
GO
-- One row
SELECT
    l.*
FROM dbo.Localized AS l 
WHERE
    l.text_body = CONVERT(SQL_VARIANT, N'Database problems' COLLATE Latin1_General_CI_AS)

-- No rows (and no collation error!)
SELECT
    l.*
FROM dbo.Localized AS l
WHERE
    l.text_body = CONVERT(SQL_VARIANT, N'Database problems' COLLATE Arabic_CI_AS)

-- One row, index seek, manual version of "LIKE 'D%'"
SELECT
    l.*
FROM dbo.Localized AS l 
WHERE
    l.text_body >= CONVERT(SQL_VARIANT, N'D' COLLATE Latin1_General_CI_AS)
    AND l.text_body < CONVERT(SQL_VARIANT, N'E' COLLATE Latin1_General_CI_AS)

通常の手順を書くこともできます:

CREATE PROCEDURE dbo.GetLocalizedString
    @text_id    INTEGER,
    @lang_id    INTEGER,
    @text_body  SQL_VARIANT OUTPUT
AS
BEGIN
    SELECT
        @text_body = l.text_body
    FROM dbo.Localized AS l
    WHERE
        l.text_id = @text_id
        AND l.lang_id = @lang_id
END
GO
DECLARE @text SQL_VARIANT

EXECUTE dbo.GetLocalizedString
    @text_id = 1001,
    @lang_id = 1025,
    @text_body = @text OUTPUT

SELECT @text

もちろん、フルテキストインデックス付けは列ごとに言語ID設定を必要とするため(すべてを除く)、「すべての翻訳用の単一テーブル」の設計ではフルテキストインデックス付けにも問題があります。Joop Eggenによって記述された複数のテーブルの設計には、フルテキストインデックスを付けることができます(当然、テーブルごとに1つのインデックスが必要です)。

もう1つの主なオプションは、ベーステーブルのロケールごとに1つの列を持つことです。

CREATE TABLE dbo.Example
(
    text_id     INTEGER NOT NULL,
    text_2057   NVARCHAR(MAX) COLLATE Latin1_General_CI_AS NULL,
    text_1025   NVARCHAR(MAX) COLLATE Arabic_CI_AS NULL,

    CONSTRAINT [PK dbo.Example text_id]
        PRIMARY KEY CLUSTERED (text_id)
)

この配置は一定の単純さを備えており、フルテキストインデックス処理で適切に機能しますが、新しい言語ごとに新しい列を追加する必要があります。多くの開発者は、この種の構造を操作するには不十分で不十分だと感じます。

それぞれの選択肢には長所と短所があり、あるレベルまたは別のレベルで間接指定が必要になるため、関係する開発者がその間接指定を見つけるのに最も満足していると感じる場所に依存する場合があります。ほとんどの人は、ほとんどの目的で複数テーブルのデザインを好むと思います。


私はおそらく、物理的なレイアウトを改善するために、個別の列ではなく個別のテーブルを使用します。それがこの質問のきっかけとなったのは私の答えでしたdba.stackexchange.com/a/9954/630
gbn

5

明らかに、言語ごとのテーブルが必要です:xxx_enxxx_frxxx_eo。それはより最適であり、言語依存の照合を可能にします。言語ごとのデータベース[en] [xxx][fr] [xxx][eo] [xxx]があることも想像できます。

その場合、技術的な詳細は二次的に重要です(それ以上最適化することはできません)。

実際のテキストキーはxxxのテーブルにあります。


2
これの問題は、それが非常に無関係であることです。
Mike Nakis、2011

はい、私の経験では、テキスト検索は、dbがサポートされているかどうかに関係なく、リレーショナルに統合するのは困難です。とにかくポイントを与えてくれてありがとう。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.