したがって、このプロジェクトは既存のコードベースを拡張しており、MySQLデータベース上に構築されています。タプルが建物内の場所を表すテーブルがあり、パスファインディング用のグラフでこれらの場所を接続するエッジを表すテーブルを作成しています。これは単純な2列のテーブルであり、各列はロケーションテーブルを参照する外部キーであるIDを保持しています。要約すると、状況は次のようになります。
CREATE TABLE node (
ID int(10) AUTO_INCREMENT NOT NULL,
(...)
PRIMARY KEY(ID)
);
CREATE TABLE edge(
ID_1 int(10),
ID_2 int(10),
FOREIGN KEY (ID_1) REFERENCES node(ID),
FOREIGN KEY (ID_2) REFERENCES node(ID)
);
グラフが対称であるという既存の仮定です。つまり、ノードAがノードBに対してエッジを持っている場合、ノードBはノードAに対してエッジを持っている必要があります。一方通行のドアの場合はここでは無視されますが、私の場合は当てはまらないようです。ドメイン。そのため、ノードAとBが接続されている場合、それらの接続は次の3つの方法のいずれかでエッジテーブルに格納できます。
{(A,B)}
{(B,A)}
{(A,B),(B,A)}
この表を使用して答える質問は、「このノードを考えると、その隣接ノードは何ですか?」です。そして現在、私のアプリケーションは次のようなクエリを使用してそれを行います。
SELECT * FROM node
WHERE ID IN(
SELECT ID_2
FROM edge
WHERE ID_1=?
UNION
SELECT ID_1
FROM edge
WHERE ID_2=?
);
ただし、私の本能は、CHECK制約を使用して、MySQLがサポートしていないと思われる後者の構造のみを格納できるようにすることでした。その答えから、そのような制約をエミュレートするには、すべてのエッジを両方の順序で格納するすべての操作のトリガーを作成する必要があります。利点は、当然のことながらパフォーマンスが向上し、質問に答えることができることです。
SELECT * FROM node
WHERE ID IN(
SELECT ID_2
FROM edge
WHERE ID_1=?
);
CHECKをエミュレートするトリガーについて読んだら、友人と話し合いました。彼は、再帰ストレージを確保するのは無駄であり(ストレージの使用量が2倍になる)、データベースを正しく処理するためにアプリケーションに任せる必要があると提案しました。今、私は実際に最善の解決策が何であるかが少しわかりません-データベースはトリガーを使用して挿入と削除を2倍にすることによって再帰性を確保する必要がありますか、それともアプリケーションは再帰的に保存されていないデータを読み取り続けて、そのように見えるようにする必要がありますか?データベースが同じデータを複数の方法で表現できるようにすると、少し心配になります。それは無理ですか?UNIONとそのようなものは、かなりのパフォーマンスヒットになりますか?
(適度に小さなサイトを対象としているため、このシステムは数万のノードを超える可能性は低く、通常のノードには最大6つのエッジがあります)。