PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Rails apa perbedaan dalam indeks unik dan validasi_uniqueness_of

Berikut adalah perbedaan antara indeks unik dan validasi_unik_of

Ini adalah tambalan untuk mengaktifkan ActiveRecord untuk mengidentifikasi kesalahan yang dihasilkan db untuk pelanggaran batasan unik. Misalnya, itu membuat pekerjaan berikut tanpa mendeklarasikan validasi_uniqueness_of:

create_table "users" do |t|
  t.string   "email",   null: false
end
add_index "users", ["email"], unique: true

class User < ActiveRecord::Base
end

User.create!(email: '[email protected]')
u = User.create(email: '[email protected]')
u.errors[:email]
=> "has already been taken"

Manfaatnya adalah kecepatan, kemudahan penggunaan, dan kelengkapan --

Kecepatan

Dengan pendekatan ini Anda tidak perlu melakukan pencarian db untuk memeriksa keunikan saat menyimpan (yang terkadang bisa sangat lambat ketika indeks terlewatkan -- https://rails.lighthouseapp.com/projects/8994/tickets/2503-validate.. . ). Jika Anda benar-benar peduli tentang memvalidasi keunikan, Anda tetap harus menggunakan batasan basis data sehingga basis data akan memvalidasi keunikan apa pun yang terjadi dan pendekatan ini menghapus kueri tambahan. Memeriksa indeks dua kali bukanlah masalah bagi DB (ini di-cache untuk kedua kalinya), tetapi menyimpan DB bolak-balik dari aplikasi adalah keuntungan besar.

Kemudahan penggunaan

Mengingat bahwa Anda harus memiliki batasan db untuk keunikan yang sebenarnya, pendekatan ini akan membiarkan semuanya terjadi begitu saja secara otomatis setelah batasan db diterapkan. Anda masih dapat menggunakan validasi_uniqueness_of jika Anda mau.

Kelengkapan

validasi_uniqueness_of selalu menjadi sedikit peretasan -- ini tidak dapat menangani kondisi balapan dengan benar dan menghasilkan pengecualian yang harus ditangani menggunakan logika penanganan kesalahan yang agak berlebihan. (Lihat bagian "Konkurensi dan integritas" di http://api.rubyonrails .org/classes/ActiveRecord/Validations/ClassMe... )

validates_uniqueness_of tidak cukup untuk memastikan keunikan suatu nilai. Alasan untuk ini adalah bahwa dalam produksi, beberapa proses pekerja dapat menyebabkan kondisi balapan:

  1. Dua permintaan bersamaan mencoba membuat pengguna dengan nama yang sama (dan kami ingin nama pengguna unik)

  2. Permintaan diterima di server oleh dua proses pekerja yang sekarang akan memprosesnya secara paralel

  3. Kedua permintaan memindai tabel pengguna dan melihat bahwa namanya tersedia

  4. Kedua permintaan lulus validasi dan membuat pengguna dengan nama yang tampaknya tersedia

Untuk pemahaman yang lebih jelas, periksa ini

Jika Anda membuat indeks unik untuk sebuah kolom, itu berarti Anda dijamin tabel tidak akan memiliki lebih dari satu baris dengan nilai yang sama untuk kolom tersebut. Menggunakan validasi_uniqueness_of hanya dalam model Anda tidak cukup untuk menegakkan keunikan karena mungkin ada pengguna bersamaan yang mencoba membuat data yang sama.

Bayangkan dua pengguna mencoba mendaftarkan akun dengan email yang sama di mana Anda telah menambahkan validasi_uniqueness_of :email dalam model pengguna Anda. Jika mereka menekan tombol "Daftar" pada saat yang sama, Rails akan melihat di tabel pengguna untuk email itu dan membalas bahwa semuanya baik-baik saja dan tidak apa-apa untuk menyimpan catatan ke tabel. Rails kemudian akan menyimpan dua catatan ke tabel pengguna dengan email yang sama dan sekarang Anda memiliki masalah yang sangat buruk untuk ditangani.

Untuk menghindari ini, Anda juga perlu membuat batasan unik di tingkat basis data:

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :email
      ...
    end
    
    add_index :users, :email, unique: true
  end
end

Jadi dengan membuat indeks unik index_users_on_email Anda mendapatkan dua manfaat yang sangat bagus. Integritas data dan kinerja yang baik karena indeks unik cenderung sangat cepat.

Jika Anda memasukkan unique:true di tabel posting Anda untuk user_id maka itu tidak akan memungkinkan untuk memasukkan catatan duplikat dengan user_id yang sama.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Optimalisasi kueri penghitungan untuk PostgreSQL

  2. Apa Kerangka Ketersediaan Tinggi PostgreSQL Terbaik? Infografis PAF vs. repmgr vs. Patroni

  3. SQL Temukan semua keturunan langsung di pohon

  4. Apakah ada alat visualisasi data untuk postgresql yang mampu menampilkan hubungan antar skema juga?

  5. Batasan pada perubahan skema PostgreSQL di dalam transaksi?