Лучший способ моделирования иерархических данных зависит от того, какие операции вам нужно поддерживать. Я бы посоветовал вам прочитать слайды Билла Карвина Модели для иерархических данных для сравнения. См., В частности, слайд 48, где приведено краткое описание сильных и слабых сторон каждого подхода.
Однако я бы не считал дружбу иерархической структурой. Обычно это циклы: A дружит с B, B дружит с C, а C дружит с A. Вместо этого вы можете создать таблицу контактов с двумя столбцами: user_id и friend_id, которые являются внешними ключами таблицы «users»:
contact_list
------------------
user_id friend_id
------------------
1 2
2 3
3 1
Чтобы получить список контактов для определенного идентификатора пользователя, выполните этот запрос:
SELECT friend_id
FROM contact_list
WHERE user_id = 1
Здесь я предполагаю, что присутствие A в списке контактов B не означает, что B также находится в списке контактов A.