質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

1回答

1392閲覧

Railsでmodelの複合キーにunique制約をつける、のイメージがわかない

dwayne_johnson

総合スコア86

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

1グッド

1クリップ

投稿2018/05/02 05:01

編集2018/05/02 06:57

RailsをAPIサーバーとして使えるように開発しています。

状況

テレビ番組を例にとり、modelには番組情報が入るProgramとテレビ局の情報が入るStationがあるとします。

Program title:string, null: false detail:text station:references, foreign_key: true, null: false start_time:datetime end_time:datetime Station name:string, null: false channel:integer, null: false

以上のような感じの構成で、すでにrails db:migrateされています。

番組の開始時間順に並び替えてjsonを吐くように作っておりますので、開始時間start_timeにindexを貼ろうと考えました。その際、テレビ局station_idstart_timeの関係はuniqueですので、unique制約を付けた方が良いのか迷っています。以下が実行予定のmigrationです。

def change remove_index :programs, column: :station_id add_index :programs, [:start_time, :station_id], unique: true end

質問

いまいちunique制約についてイメージが掴めていないのですが、例えば全データの中から.find_by()を使いstation_idで絞り込んで、そこからProgramsの情報を開始時間順に取り出す場合について考えます。

この時、unique制約があることで、どのような仕組みで速くデータが取り出せる(SQLの呼び出しが少なくて済む?)のかがいまいちわかりません。というかそもそも、この場合にunique制約が必要なのかもイマイチわかりません。。

また、こちらには"unique indexの順序"とありますが、これは逆にすると何かがかわるのか、どのように"使えそうな順序"を判断すればよいのかもわかりません。

どなたか、ご教授お願いします。

解決に際し、参考になったサイト

UNIQUEインデックスとは
UNIQUE制約とは
複合インデックスとは

kawakawa2018👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

走り書きになりますが少しだけ回答しておきます。

unique制約があることで、どのような仕組みで速くデータが取り出せる(SQLの呼び出しが少なくて済む?)のかがいまいちわかりません。

unique制約
unique index(unique索引)

というのは、データベースの索引の話です。


まず整理すると

unique index(unique索引) 
これは
「検索」機能に対して働くデータベースの速度向上の仕組みです。
そしてこれを使うことで、データベースはB-tree(2分木)や
ビットマップインデックスという「速くデータが取り出せる」仕組みが使えます。
これが1つ目の疑問の回答です。

次ですがunique制約と、もう1つ別の制約があります。
unique制約と、uniqueでない制約があります。
uniqueでない制約は、「一意ではない」つまり重複を許すカラムに対して
検索のためにつける制約です。

そして一意なカラムに索引をつけて、検索向上をする場合
unique制約をつけます(定義します)。


ですので

この場合にunique制約が必要なのか
の問いには

テレビ局station_id(またはstation?)カラムは
一意な(uniqueな)カラムなので
unique制約をつけます。

また

**テレビ局station_idとstart_timeの関係はuniqueですので、unique制約を付けた方が良いのか
**

ですが、上の回答を読んでいただければ
このご自身の認識が間違いであるとわかるでしょう。
(station_idとstart_timeの関係はunique ではなく・・・)


unique indexの順序"とありますが、これは逆にすると何かがかわるのか、どのように"使えそうな順序"を判断すればよいのか

複合キーをきちんと利用するの内容は
正直、不親切だと思いました。

順序は 理論的には・。。

自然キーや複合キーがあるのであれば、それを意識し、正しく扱うことが重要であることは変わらない。
といっても基本的にはunique indexはるだけではある

のくだりなど。
もっと詳しい正しい説明があるので、サイトを探して読んでみてください。
ここでは簡単に。

def change remove_index :programs, column: :station_id add_index :programs, [:start_time, :station_id], unique: true end

せっかくなので、こちらの実行メソッドを
見直してみてください。

他の方が回答だけ示すかもしれませんが、
いい感じで学習、学ばれている感じがしますので、
ここで回答をとめておきます。

結構大事だと思います、こういう思考の過程。
それでは。

投稿2018/05/02 05:55

kawakawa2018

総合スコア1195

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dwayne_johnson

2018/05/02 06:53

なるほど、まず前提としてUNIQUEインデックスとUNIQUE制約についてごっちゃになっていました。 とりあえずこの2つ、そしてindexがどう働くのかについて理解した上で、複合インデックスについて調べることで問題が解決しました。 "最初の列は並べ替えの優先順位が最も高く、最初の列に同じ値が複数ある時に限り、2番目の列でも並べ替えがされます。" https://use-the-index-luke.com/ja/sql/where-clause/the-equals-operator/concatenated-keys つまり、自分の場合では :station_id が一意ですので、 add_index :programs, [:station_id, :start_time], unique: true のような書き方にすることで、:station_id ごとに並び替えられたうえで :start_time順に並んだindexが作成され、自分が行いたい検索の際に有意に働くということ、ですね。 具体的には station_id | start_time | 1 | 5:00 | 1 | 6:00 | 1 | 7:00 | 2 | 5:00 | 2 | 6:00 | 3 | 5:00 | のようなイメージで。 とりあえず自分の中ではすっきりしました。RDBについて、学びが深まる良い機会になりました。 いい感じにご回答いただき、ありがとうございました。大変たすかりました。
kawakawa2018

2018/05/02 12:35

こんばんは ”大変たすかりました。” いいえどういたしまして。 熱心ですね。 GW連休の谷間ですが、気晴らしをしつつ じっくりと、しかし戸惑うことなく エラーやトラブルに向き合ってください。 ここまでは理解できた、正しく作業したと 実感しながら前に進んでください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問