2

これは、しばらく私を悩ませてきた精神的なエクササイズです。この種の問題を解決するには、どのような戦略を使用しますか?

次の単純なデータベース構造を考えてみましょう。ディレクトリがあり、明らかにそれらのツリーです。また、常にいくつかのディレクトリに常駐するコンテンツ アイテムもあります。

create table directory ( 
 directoryId integer generated always as identity primary key,
 parentId integer default null,
 directoryName varchar(100)
);

create table content (
 contentId integer generated always as identity primary key,
 directory integer references directory(directoryId),
 contentTitle varchar(100),
 contentText varchar(32000)
);

ここで、ディレクトリ ツリーが巨大で、コンテンツの量が膨大であると仮定しましょう。ソリューションは適切にスケーリングする必要があります。

主な問題: 指定されたディレクトリとそのサブディレクトリから見つかったすべてのコンテンツ アイテムを効率的に取得する方法は?

私の見方では、SQL を使用してサブセレクトのすべての directoryIds を簡単に取得することはできません。私は正しいですか?

単純な再帰ループを使用して、アプリケーション側でこれを解決できます。ただし、これは実際には非常に重くなる可能性があり、特に妥当な最初のアクセス時間を隔離するために、トリッキーなキャッシングが必要になる場合があります。

マテリアライズド クエリ テーブルを作成し、多次元インデックスを動的に追加することもできます。可能ですが、実装の混乱。複雑すぎる。

私の最も好きな解決策は、おそらく次のような新しいテーブルを追加することです

create table subdirectories (
 directoryId integer,
 subdirectoryId integer,
 constraint thekey primary key (directoryId,subdirectoryId)
)

ディレクトリが移動/削除/作成されているときは、常に手動で更新するようにしてください。したがって、常に directoryId を使用して選択を行い、より複雑なクエリのサブ選択を含め、サブディレクトリのすべての ID を取得できます。また、rdbms がクエリを適切に最適化できることも気に入っています。

皆さんはどう思いますか?

4

2 に答える 2

4

SQL Server 2005PostgreSQL 8.4およびOracle 11g: _

WITH    
        -- uncomment the next line in PostgreSQL
        -- RECURSIVE
        q AS
        (
        SELECT  directoryId
        FROM    directories
        WHERE   directoryId = 1
        UNION ALL
        SELECT  d.directoryId 
        FROM    q
        JOIN    directories
        WHERE   parentId = q.directoryId
        )
SELECT  c.*
FROM    q
JOIN    content c
ON      c.directory = q.directoryId

Oracle前に11g

SELECT  c.*
FROM    (
        SELECT  directoryId
        FROM    directories
        START WITH
                directoryId = 1
        CONNECT BY
                parent = PRIOR directoryID
        ) q
JOIN    content c
ON      c.directory = q.directoryId

以下についてPostgreSQL 8.3は、この記事を参照してください。

についてMySQLは、次の記事を参照してください。

于 2010-02-28T20:12:27.543 に答える
1

これは、SQL の標準であり、よく理解されている「困難な問題」です。

アークノード グラフ理論の問題はすべて、推移的な関係を伴うため難しいものです。

標準的なソリューションがあります。

  1. ツリーの未訪問ノードのリストを管理するために使用する明示的なスタックでループします。

  2. 再帰。これは非常に効率的です。「トリッキーなキャッシングは必要ありません」。本当にシンプルで効果的です。再帰スタックは、未訪問のノードのリストです。

  3. ディレクトリ ツリーの 「推移閉包」を作成します。

  4. ディレクトリ ツリーのような推移的な関係を処理するための SQL 拡張機能。

于 2010-02-28T20:14:47.940 に答える