28

これは、ActiveRecord クエリ メソッドに関する質問です。

  • first最初のレコード (パラメーターが指定されている場合は最初の N レコード) を検索します。順序が定義されていない場合は、主キーで順序付けされます。
  • take暗黙の順序なしでレコード (パラメーターが指定されている場合は N レコード) を指定します。順序は、データベースの実装によって異なります。注文が提供された場合、それは尊重されます。

ユースケース: 一意の属性に基づいてデータベースからレコードを取得します (例)。

User.where(email: 'f@example.com')

ここで、 first生成します

SELECT "users".* FROM "users" WHERE "users"."email" = 'f@example.com' ORDER BY "users"."id"` ASC LIMIT 1

take生成する

SELECT "users".* FROM "users" WHERE "users"."email" = 'f@example.com' LIMIT 1

上記のようfirstに、追加の順序句が追加されます。takevsの間にパフォーマンスの違いがあるかどうか疑問に思っていfirstます。

takeよりも高速ですか、firstそれともその逆ですか?

4

1 に答える 1

43

一般に、データベースは基準を満たすすべての行を識別し、それらを並べ替えて、並べ替えが最も低い行を見つける必要がないため、「取得」の方が高速です。「テイク」を使用すると、データベースは単一の行が見つかるとすぐに停止できます。

高速化の程度は、次のように異なります。

  1. 複数の行を探す必要がなくなることで、どれだけの時間が節約されるか。ここでの最悪のケースは、大きなテーブルのフル スキャンが必要な場合ですが、スキャンの非常に早い段階で一致する行が 1 つ見つかった場合です。「取る」を使用すると、スキャンを停止できます。

  2. 最小の ID を持つ行を見つけるためにソートする必要がある行の数。ここでの最悪のケースは、テーブル内のすべての行が条件に一致し、並べ替えに含める必要がある場合です。

他にも考慮すべき要素がいくつかあります。たとえば、「最初の」クエリの場合、オプティマイザは主キー インデックスのスキャンを介してテーブルにアクセスし、各行をチェックして条件に一致するかどうかを確認できます。その可能性が非常に高い場合、クエリ オプティマイザーが十分に洗練されていれば、データの完全なスキャンと並べ替えの両方を回避できます。

多くの場合、一致するレコードとそれらを見つけるためのインデックスベースのアクセスがほとんどない場合、違いは些細なものであることがわかります (例では「email」に一意のインデックスがある場合)。ただし、それでも最初よりも優先して「テイク」を使用します。

編集:少し話題から外れていますが、あなたの例では次のように使用することもできます:

User.find_by(email: 'f@example.com')

生成されたクエリは take とまったく同じはずですが、セマンティクスはもう少し明確だと思います。

于 2013-08-28T21:11:21.997 に答える