0

私は2つのモデルを持っています-QuestionそしてTag-それらの間にHABTMがあり、それらは結合テーブルを共有していますquestions_tags

このバッドボーイにあなたの目を楽しませてください:

1.9.3p392 :011 > Question.count
   (852.1ms)  SELECT COUNT(*) FROM "questions" 
 => 417 
1.9.3p392 :012 > Tag.count
   (197.8ms)  SELECT COUNT(*) FROM "tags" 
 => 601 
1.9.3p392 :013 > Question.connection.execute("select count(*) from questions_tags").first["count"].to_i
   (648978.7ms)  select count(*) from questions_tags
 => 39919778 

結合テーブルに多数の重複レコードが含まれていると想定していquestions_tagsます。そうでない場合、なぜこれほど大きくなるのかわかりません。

uniqその結合テーブルをクリーンアップして、コンテンツのみが含まれるようにするにはどうすればよいですか?または、重複するレコードがそこにあるかどうかを確認するにはどうすればよいですか?

編集1

私はPostgreSQLを使用しています。これはjoin_tableのスキーマです。questions_tags

  create_table "questions_tags", :id => false, :force => true do |t|
    t.integer "question_id"
    t.integer "tag_id"
  end

  add_index "questions_tags", ["question_id"], :name => "index_questions_tags_on_question_id"
  add_index "questions_tags", ["tag_id"], :name => "index_questions_tags_on_tag_id"
4

2 に答える 2

2

前回とは大きく異なるため、これを新しい回答として追加します。idこれは、結合テーブルに列があることを想定していません。これにより、新しいテーブルが作成され、一意の行が選択され、古いテーブルが削除され、新しいテーブルの名前が変更されます。これは、サブセレクトを含むものよりもはるかに高速です。

foo=# select * from questions_tags;
 question_id | tag_id
-------------+--------
           1 |      2
           2 |      1
           2 |      2
           1 |      1
           1 |      1
(5 rows)

foo=# select distinct question_id, tag_id into questions_tags_tmp from questions_tags;
SELECT 4
foo=# select * from questions_tags_tmp;
 question_id | tag_id
-------------+--------
           2 |      2
           1 |      2
           2 |      1
           1 |      1
(4 rows)

foo=# drop table questions_tags;
DROP TABLE
foo=# alter table questions_tags_tmp rename to questions_tags;
ALTER TABLE
foo=# select * from questions_tags;
 question_id | tag_id
-------------+--------
           2 |      2
           1 |      2
           2 |      1
           1 |      1
(4 rows)
于 2013-03-13T00:51:15.700 に答える
1

タグ参照が不適切なタグの関連付けを削除する

DELETE  FROM questions_tags
WHERE   NOT EXISTS ( SELECT  1 
                 FROM    tags
                 WHERE   tags.id = questions_tags.tag_id);

質問への参照が不適切なタグの関連付けを削除する

DELETE  FROM questions_tags
WHERE   NOT EXISTS ( SELECT  1 
                 FROM    questions
                 WHERE   questions.id = questions_tags.question_id);

重複するタグの関連付けを削除する

DELETE  FROM questions_tags
USING   ( SELECT qt3.user_id, qt3.question_id, MIN(qt3.id) id
          FROM   questions_tags qt3
          GROUP BY qt3.user_id, qt3.question_id
        ) qt2
WHERE   questions_tags.user_id=qt2.user_id AND 
        questions_tags.question_id=qt2.question_id AND
        questions_tags.id != qt2.id

ノート:

本番環境で試す前に、開発環境で SQL をテストしてください。

于 2013-03-12T23:19:28.007 に答える