2016-04-05 10 views
2

私のアプリでは、いくつかの共通のプロパティを共有するいくつかのエンティティがあります。例エンティティ:Doctrine継承のパフォーマンス

  • 画像
  • ビデオ
  • イベント
  • ForumPost

私はこれらのクラスは、いくつかの共通の機能を共有したい、といった:

  • は、リストを持っていますコメントの数を保持すると同時に、
  • 投票
  • 加入者と加入者の
  • 一覧は
  • ビューが
  • などをカウントを数える。..

私は実際に上記の各エンティティのためにこれらの機能を複製したいとは思わないでしょう。だから...私はDoctrineの継承マッピングについて読んできましたが、これを解決する最もエレガントな方法は "クラステーブル継承"というアイデアです。

class PostLike 
{ 
    /** 
    * @ORM\ManyToOne(targetEntity="Post") 
    * @ORM\JoinColumn(name="post_id", referencedColumnName="id", nullable=false) 
    */ 
    protected $post; 
} 

  1. /** 
    * @ORM\Entity 
    * @ORM\InheritanceType("JOINED") 
    * @ORM\DiscriminatorColumn(name="type", type="string") 
    */ 
    class Post 
    { 
        protected $likeCount; 
    
        protected $subscriberCount; 
    
        protected $subscribers; 
    
        // ... 
    } 
    
  2. がエンティティを投稿するのが好き、コメント、投票などの多対一の関係を持つ親のポストエンティティを作成します。以下のように計画でした

  3. 画像、動画などのエンティティを拡張してください投稿:

    class Video extends Post 
    { 
        // Post properties become available here 
    } 
    

Doctrineが実行している実際のクエリを見るまで、すべてcharmのように働いていました。問題は、私がPostLikeを選択するたびに、doctrineはPostエンティティも積極的に読み込み、すべての子テーブルも結合することになります。たとえば、単純なPostLikeの削除操作では、4つの表の結合がトリガーされ、実際には階層が拡大するにつれ、さらに多くの表に結合されます。

私が10個のエンティティをPostに拡張すると、10個のテーブルが結合されます。私は早すぎる最適化のファンではありませんが、これは良い計画のようには聞こえません。

Doctrineのドキュメントでは、この動作は「6.3.2パフォーマンスの影響」で実際に言及されています。

最後に、私の質問doctrineで再利用可能なテーブルを作成する私の他のオプションは何ですか?

私はOne-To-Oneマッピング(投稿エンティティはVideoやImageなどのプロパティです)を行うことを考えていましたが、私はいくつかのブログでone-パフォーマンス上の理由からも、教義は避けるべきです。

ありがとうございました!マップされたスーパークラスに関するラファエルマリーへ

編集とansewer:

私はマップされたスーパークラスと形質を使用できることを認識していますが、コードの重複を避けるために備わっています。しかし、これらの機能を使用するとコードを再利用できますが、SQLテーブルを再利用することはできません。ここに例があります:

私は、イメージ、ビデオ、およびイベントエンティティにコメントを付けることを望みます。 1つのMapped Superclass AbstractCommentを作成し、それをImageComment、VideoComment、EventCommentで拡張することができます。次に、私はコメント投票を追加したいと思います。私は同じSQLテーブルを再利用することができないので、私はImageCommentVote、VideoCommentVote、EventCommentVoteなどを作成する必要があります。そして、ユーザーが悪質なコメントを報告できるようにします。もう一度やります:ImageCommentReport、VideoCommentReport、EventCommentReportあなたはその考えを得る。私がコメントに追加したいすべての機能には、イメージ、ビデオなどの各エンティティごとに別々のテーブルが必要です。テーブルがたくさんあります。

私が代わりに多くのテーブルで特性を使用しての集中型のアプローチを使用することを好む理由:

  • 容易な管理。私は簡単に1つのテーブルにクエリを送信することによって、アプリケーション全体のコメントを検索/編集/削除することができます。
  • 複数のエンティティのアクションを同じコントローラで処理できます。抽象的な抽象的なコントローラを1つ作成する必要はありません。
  • アクションが集中化されている場合、新しいコメントやお気に入りなどのユーザー通知をもっと簡単に表示できます。

私はこのようなシステムの欠点も認識していますが、私は今のところそれらと一緒に暮らすことができます。私の質問は、Doctrineに、必要でないときにすべてを実際に参加させることなく、私が望むことをやり遂げる方法です。

+0

ほぼ2年後、私は非常に興味があります。あなたはどのような解決策をとったのですか? – BigJ

答えて

1

私の意見では間違っています。いくつかの機能を除いて、エンティティには何も共通していないので、single tableまたはclass tableの継承を使用する理由はありません。

あなたはトレイトを使用する必要があります。http://php.net/manual/en/language.oop5.traits.php

それは教義で動作します。注釈付きのいくつかのプロパティ/メソッドを持つ1つまたは複数の特性を定義し、これらの特性をエンティティにインポートします。

マッピングされたスーパークラス:http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/inheritance-mapping.html#mapped-superclassesを使用することもできますが、これはあなたの例に非常に近いものの、エンティティアノテーションは異なります。

+0

Traitsとマップされたスーパークラスは、私が各エンティティに対して異なるコメントテーブルを(例えば)使用するように強制します。だから私はVideoComment、ImageComment、EventCommentなどを使う必要があります。もし私がコメント投票を追加したいのであれば、私はVideoCommentVote、ImageCommentVote、...を使う必要があります。私がしたいことは、ビデオや画像、または他のクラスに関連することができる1つのCommentエンティティを持つことです。同じことは、好き嫌い、購読などにも適用されます – Karolis

0

考えてみると、あなたの決定は実際にはデータベースのサイズによって決まります。それが大きい場合、Class Tabelアプローチのパフォーマンスヒットは受け入れられないかもしれません。しかし、あなたのテーブルが小さい場合、パフォーマンスヒットは軽微で、クラステーブル継承のすべての利点を使用することができます。