Saya mengembangkan hubungan pertemanan di MySQL di mana hubungan pertemanan saling menguntungkan. Jika A adalah teman B, maka B adalah teman A. Jika salah satu pengguna mengakhiri pertemanan maka relasinya turun. Saya ingin belajar mana yang lebih baik.
Saya memiliki sistem yang sedang berjalan;
user
-----------
userid p.k
name
friends
-------
userid
friendid
primary key (`userid`,`friendid`),
key `friendid` (`friendid`)
1 2
2 5
1 3
To get all of my friends;
SELECT u.name, f.friendid , IF(f.userid = $userid, f.friendid, f.userid) friendid
FROM friends f
inner join user u ON ( u.userid = IF(f.userid = $userid, f.friendid, f.userid))
WHERE ( f.userid = '$userid' or f.friendid = '$userid' )
Kueri ini berfungsi dengan baik. Mungkin saya bisa menambahkan UNION
. Kueri lebih rumit daripada yang di bawah ini dan tabel tersebut berisi setengah dari jumlah rekaman seperti yang di bawah ini.
Cara lain adalah menjaga hubungan di baris yang terpisah;
1 2
2 1
2 5
5 2
1 3
3 1
SELECT u.name, f.friendid
FROM friends f inner join user u ON ( u.userid = f.friendid )
WHERE f.userid = '$userid'
Kueri ini sederhana, meskipun tabel membutuhkan ruang dua kali lebih banyak.
Kekhawatiran saya adalah; dengan asumsi bahwa ada jutaan pengguna; jalan mana yang akan bekerja lebih cepat?
Apa kelebihan dan kekurangan dari kedua cara tersebut?
Apa yang harus saya ingat atau ubah untuk cara-cara ini? Dan masalah apa yang bisa saya hadapi untuk kedua cara?
sumber
Jawaban:
Hal pertama yang menarik perhatian saya adalah pengaturan indeks untuk
friends
.Anda memiliki ini saat ini:
Saat memeriksa ulang untuk persahabatan bersama, hal itu dapat menimbulkan sedikit biaya karena userid dapat diambil dari tabel saat melintasi
friendid
indeks. Mungkin Anda bisa mengindeks sebagai berikut:Ini dapat menghapus kebutuhan untuk mengakses tabel dan mencari indeks saja.
Sekarang, dalam hal kueri, keduanya dapat meningkat dengan indeks unik baru. Membuat indeks unik juga menghilangkan kebutuhan untuk memasukkan
(A,B)
dan(B,A)
ke dalam tabel karena(A,B)
dan(B,A)
akan tetap menjadi indeks. Dengan demikian, kueri kedua tidak harus melalui tabel untuk melihat apakah seseorang adalah teman orang lain karena orang lain yang memulai persahabatan. Dengan begitu, jika pertemanan dipatahkan oleh satu orang saja, tidak ada persahabatan yatim yang satu sisi (sepertinya sangat mirip dengan kehidupan akhir-akhir ini, bukan?)Permintaan pertama Anda sepertinya akan mendapat manfaat lebih dari indeks unik. Bahkan dengan jutaan baris, mencari teman menggunakan indeks saja tidak akan menyentuh meja. Namun, karena Anda tidak menyajikan kueri UNION, saya ingin merekomendasikan kueri UNION:
Ini akan membuat Anda melihat siapa teman dari setiap userid
Untuk melihat semua pertemanan, jalankan ini:
Pertama, ini beberapa data sampel:
Mari kita lihat semua hubungannya
Mari kita lihat ke-5 userid dan lihat apakah hubungannya ditampilkan dengan benar
Mereka semua terlihat benar bagiku.
Sekarang, mari gunakan permintaan kedua Anda untuk melihat apakah itu cocok ...
Kenapa tidak cocok? Itu karena saya tidak memuat
(B,A)
untuk setiap(A,B)
. Biarkan saya memuat(B,A)
hubungan dan coba permintaan kedua Anda lagi.Mereka masih belum cocok. Itu karena permintaan kedua Anda hanya memeriksa satu sisi.
Mari kita periksa permintaan pertama Anda terhadap setiap nilai hanya dengan (A, B) dan tidak (B, A):
Pertama Anda bekerja dengan baik. Saya yakin itu mendapat manfaat dari indeks unik seperti yang saya katakan sebelumnya, tapi IMHO saya pikir UNION lebih sederhana. Dengan indeks unik, akan tampak enam dari satu setengah lusin lainnya dalam hal eksekusi dan output.
Anda harus membandingkan permintaan pertama Anda dengan UNION saran saya dan lihat.
Ini adalah pertanyaan bagus yang Anda tanyakan hari ini. +1 untuk pertanyaan Anda.
sumber
friendid
,userid
) dan sekarang hasilnya sekitar 0,00794 Apakah ini secepat mungkin? Melihat hasilnya apakah menurut Anda cara pertama lebih baik (satu baris untuk setiap relasi)? Karena ini dua kali lebih sedikit ruang daripada yang kedua dan hasilnya hampir sama dengan pengaturan saat ini.WHERE
,GROUP BY
danORDER BY
klausa menghasilkan data yang dibaca dari indeks saja. Berikut adalah beberapa tautan bagus yang membenarkan penggunaan kunci unik dan utama sebagai meliputi indeks: 1) peter-zaitsev.livejournal.com/6949.html , 2) mysqlperformanceblog.com/2006/11/23/… , 3) ronaldbradford .com / blog / tag / meliputi-indeks