Bu yazı Ben mümkün olduğunca açık olmaya çalışıyorum çünkü yazmanız için zaman önemli bir miktarda alarak, bu yüzden hala belirsiz olup olmadığını lütfen bana ayı edilir.
Temelde, ne sahip kullanıcılar için gizlilik ayarlarını ekleyebilirsiniz veritabanındaki yazıların bir tablo vardır.
ID | owner_id | post | other_info | privacy_level (int value)
Oradan, kullanıcıların tüm [PRIVACY_LEVEL = 0), arkadaşlar (PRIVACY_LEVEL = 1), kimse (PRIVACY_LEVEL = 3), ya da belirli kişi veya filtreler (PRIVACY_LEVEL = 4) tarafından görüntülenebilir olmasını sağlayan, kendi gizlilik ayrıntıları ekleyebilirsiniz. Belirli insanlar (4) belirterek gizlilik düzeyleri için, sorgu kullanıcı tablodaki bir satır var (ya da bir filtre kullanıcının ait) görmek için bir alt sorguda tablo "post_privacy_includes_for" referans olacaktır.
ID | post_id | user_id | list_id
Ayrıca, kullanıcı (herkes görüntülemek için ayarlanmış olması ama bir iz kullanıcıdan gizleyerek, örneğin) hariç tutarak, daha büyük bir grup içinde kendi görevini inceleyen bazı engellemek için yeteneğine sahiptir. Bunun için, başka bir referans tablo, "post_privacy_exclude_from" eklenir - bu "post_privacy_includes_for" olarak kurulum aynı görünüyor.
Benim sorunum bu ölçek olmamasıdır. Tüm. Şu anda, yaklaşık 1-2 milyon mesaj vardır, bunların çoğunluğu herkes tarafından görülebilir olarak ayarlanır. Bu 100-200 mesajlar ile dolu olabilir bir sayfada gerçekten yavaş hareket - sayfadaki her yazı için o kullanıcıya gösterilen olmaktan mesajı hariç bir satır olup olmadığını görmek için kontrol etmelisiniz. Bu ek kısıtlamaları sorguya eklendiğinde, özellikle 2-4 saniye kadar sürebilir.
Bu aynı zamanda sadece ... garip son derece büyük ve karmaşık sorguları oluşturur.
SELECT t.*
FROM posts t
WHERE ( (t.privacy_level = 3
AND t.owner_id = ?)
OR (t.privacy_level = 4
AND EXISTS
( SELECT i.id
FROM PostPrivacyIncludeFor i
WHERE i.user_id = ?
AND i.thought_id = t.id)
OR t.privacy_level = 4
AND t.owner_id = ?)
OR (t.privacy_level = 4
AND EXISTS
(SELECT i2.id
FROM PostPrivacyIncludeFor i2
WHERE i2.thought_id = t.id
AND EXISTS
(SELECT r.id
FROM FriendFilterIds r
WHERE r.list_id = i2.list_id
AND r.friend_id = ?))
OR t.privacy_level = 4
AND t.owner_id = ?)
OR (t.privacy_level = 1
AND EXISTS
(SELECT G.id
FROM Following G
WHERE follower_id = t.owner_id
AND following_id = ?
AND friend = 1)
OR t.privacy_level = 1
AND t.owner_id = ?)
OR (NOT EXISTS
(SELECT e.id
FROM PostPrivacyExcludeFrom e
WHERE e.thought_id = t.id
AND e.user_id = ?
AND NOT EXISTS
(SELECT e2.id
FROM PostPrivacyExcludeFrom e2
WHERE e2.thought_id = t.id
AND EXISTS
(SELECT l.id
FROM FriendFilterIds l
WHERE l.list_id = e2.list_id
AND l.friend_id = ?)))
AND t.privacy_level IN (0, 1, 4))
AND t.owner_id = ?
ORDER BY t.created_at LIMIT 100
(Bu bir karışıklık var. Ben Doktrini ORM şimdi kullanmak sorgusuna benzer bir sorgu, kadar alay, ama ben söylüyorum ne olsun.)
Benim soru bunu nasıl optimize etmek için bu durum yaklaşım olurdu sanırım? Benim veritabanını kurmak için daha iyi bir yolu var mı? Tamamen ben şu anda inşa var yöntemini hurda hazırım, ama ben üzerine taşımak ne bilemeyiz.
Teşekkürler çocuklar.
Güncelleme: (I değerleri basitleştirilmiş çünkü güncellemek için unuttum) Yukarıda gizlilik düzeyi için tanımlanan değerleri yansıtacak şekilde sorguyu Fix