4

私は現在、真に最初の PHP アプリケーションを作成しています。MySQL ビューを適切にプロジェクト/設計/実装する方法を知りたいです。

私の特定のケースでは、ユーザーデータは(データベースの正規化の結果として)複数のテーブルに分散されており、ビューを使用してデータを1つの大きなテーブルにグループ化することを考えていました:

CREATE VIEW `Users_Merged` (
name,
surname,
email,
phone,
role
) AS (
SELECT name, surname, email, phone, 'Customer'
FROM `Customer`
)
UNION (

SELECT name, surname, email, tel, 'Admin'
FROM `Administrator`
)
UNION (

SELECT name, surname, email, tel, 'Manager'
FROM `manager`
);

このようにして、PHP アプリからビューのデータを簡単に使用できますが、これがパフォーマンスにどの程度影響するかはよくわかりません。

例えば:

SELECT * from `Users_Merged` WHERE role = 'Admin';

ビューのデータをフィルタリングする正しい方法ですか、それともビュー自体を作成する前にフィルタリングする必要がありますか? (これは、ユーザーのリストと、ユーザーをロールでフィルタリングする機能を持たせるために必要です)。

編集

具体的に私が取得しようとしているのは、3 つのテーブルを 1 つに非正規化することです。私の解決策は正しいですか? ウィキペディアの非正規化を参照してください

4

3 に答える 3

3

通常、データベース エンジンが最適化を実行します。つまり、他のテーブルに結合する前に users テーブルをフィルタリングする必要があることをエンジンが判断するということです。

したがって、先に進んでビューを使用し、データベースに心配させてください。

後でパフォーマンスの低下を検出した場合は、MySQL EXPLAIN を使用して、MySQL が何を行っているかを通知します。

PS: あなたのデータ設計では、ユーザーごとに 1 つのロールしか許可されていません。それはあなたが望んでいたことですか? その場合、および指定したクエリの例が頻繁に実行する予定のクエリである場合は、ユーザーのロール列に必ずインデックスを付けてください。

于 2010-03-15T15:48:45.840 に答える
1

ユーザー数が 1000 人未満の場合 (可能性が高いと思われます)、どのように実行するかは問題ではありません。ユーザー リストが長期間変更される可能性が低い場合、おそらくパフォーマンスの観点からできる最善の方法は、ユーザー リストをメモリにロードし、データベースにはまったくアクセスしないことです。その間にユーザー データが変更された場合でも、データベースだけでなくインメモリ構造も更新でき、DB からユーザー情報を読み取る必要はありません。

于 2010-03-15T16:07:56.817 に答える
0

おそらく、管理者、ユーザー、マネージャー、およびあなたが持っているものを、多くの重複を節約する識別子列「ロール」を使用して1つの均一なテーブルに正規化する方がはるかに良いでしょう。これが本質的に最初に正規化を行う理由です場所。次に、ロール固有の詳細を、結合でユーザー テーブルと一緒に使用する個別のテーブルに追加できます。

クエリは次のように単純になります。

SELECT
   `Name`, `Surname`, `Email`, `Phone`, `Role`
FROM `User`
WHERE 
    `User`.`Role` IN('Administrator','Manager','Customer', ...)

unionまた、一連のsよりもデータベースが処理しやすいもの

さらに一歩進んで、ユーザーがユーザーごとに持っているすべてのロールを保持するテーブルを ( の列UserRoleCouplingの代わりに) 追加できます。RoleUser

CREATE TABLE `UserRoleCoupling` (
    UserID INT NOT NULL,  -- assuming your User table has and ID column of INT
    RoleID INT NOT NULL,
    PRIMARY KEY(UserID, RoleID)
);

実際のロール情報も別のテーブルに入れます。

CREATE TABLE `Role` (
    ID INT NOT NULL UNIQUE AUTO_INCREMENT,
    Name VARCHAR(64) NOT NULL
    PRIMARY KEY (Name)
)

ユーザーごとに複数のロールを持ち、次のようなクエリを使用できるようになりました

SELECT
    `U`.`Name`
   ,`U`.`Surname`
   ,`U`.`Email`
   ,`U`.`Phone`
   ,GROUP_CONCAT(`R`.`Name`) `Roles`
FROM `User`
INNER JOIN `UserGroupCoupling` `UGC` ON `UGC`.`UserID` = `User`.`ID`
INNER JOIN `Role` `R` ON `R`.`ID` = `UGC`.`RoleID`
GROUP BY
    `U`.`Name`, `U`.`Surname`, `U`.`Email`, `U`.`Phone`

これにより、基本的なUser詳細と、割り当てられたすべての名前のカンマ区切りのリストが得られRoleます。

一般に、データベース構造を正規化する最善の方法は、テーブルを冗長にならないようにできるだけ汎用的にすることです。そのため、管理者や顧客固有の詳細をユーザー テーブルに追加するのではなく、 と の関係を使用しUserAdministrator特定の管理者を見つけます。詳細。あなたが今やっているやり方は、本当に標準化されていません。

データベースの正規化に関する私のお気に入りの本を見つけて、後で時間があるときに ISBN を投稿できるかどうかを確認します。

于 2010-03-15T18:53:52.307 に答える