последние посетители - PullRequest
       6

последние посетители

3 голосов
/ 12 января 2010

Допустим, вы хотите отображать последних посетителей на странице профиля пользователя. Как бы вы это структурировали? Возможно, таблица называется uservisitors:

  • идентификатор пользователя (пользователь, который получает посещение)
  • посетитель (посетитель)
  • время

И как бы вы выбрали это с MySQL? Без каких-либо дубликатов я имею в виду, что если пользователь 1 посещает профиль пользователя 2, а затем через 5 минут снова посещает, я не хочу, чтобы обе записи отображали только последние

ура!

Ответы [ 6 ]

4 голосов
/ 12 января 2010
SELECT  visitorid, MAX(time) AS lastvisit
FROM    uservisitors
WHERE   userid = ?
GROUP BY
        userid, visitorid
ORDER BY
        lastvisit DESC
LIMIT 5

Создайте составной индекс на (userid, visitorid, time), чтобы он работал быстрее.

Этот запрос:

SELECT  visitorid
FROM    uservisitors ui
WHERE   userid = ?
        NOT EXISTS
        (
        SELECT  NULL
        FROM    uservisitors uo
        WHERE   uo.userid = ui.userid
                AND uo.visitorid = ui.visitorid
                AND uo.time > ui.time
        )
ORDER BY
        time DESC
LIMIT 5

может быть более эффективным, если у вас много разных посетителей.

В этом случае вам понадобится индекс для (userid, time, visitorid).

Обновление:

В этой статье моего блога сравниваются оба подхода:

0 голосов
/ 14 января 2010

Я имел дело с этим несколько раз, вот мое мнение.

Мой стол выглядит так:

CREATE TABLE visitors (
userid int,
visitorid int,
last_visit datetime,
primary key(userid, visitorid),
index(visitorid)
index(userid, last_visit)
) engine = memory;

Вставка данных:

INSERT INTO visitors (userid, last_visit) VALUES ( 50, now() ) 
ON DUPLICATE KEY UPDATE last_visit = now();

Выбор:

select * from visitors WHERE userid=10 order by last_visit limit 10; # or whatever you need

Время от времени очищайте таблицу

DELETE from visitors WHERE last_visit < date_add(now(), INTERVAL -1 WEEK);

Это путь по нескольким причинам.

  1. Вы используете таблицу в памяти, поэтому вы никогда не касаетесь диска.
  2. Индекс включен (visitorid, last_update), так что это чистый поиск по индексу. Очень быстро. Даже без этого все должно быть быстро.
  3. Извлечение пользователей с помощью отдельного запроса позволит вам их кэшировать, но теоретически они должны быть уже кэшированы, если они недавно посещали сайт. Даже если вы не используете кеш, запрос in () для пользователя (первичный ключ) должен быть очень быстрым.

Вы можете запускать cron для резервного копирования этой таблицы раз в минуту

SELECT * from visitors INTO OUTFILE "/tmp/visitors.txt"
0 голосов
/ 13 января 2010

Как вы планируете удалять вещи из таблицы позже? Вам может понадобиться добавить еще один индекс, чтобы это работало эффективно.

Если вам нужны только последние 5 посещений, я бы денормализовал таблицу (сохраняет пространство, индексировал и использовал только один поиск первичного ключа), и в процессе мне больше не пришлось бы беспокоиться об удалении старых данных. Каждый пользователь будет занимать только одну строку в таблице, поэтому он не будет сильно расти со временем. Итак:

CREATE TABLE user_visitors (user_id int primary key,
visitor_1_id int,
visitor_1_time timestamp,
..
visitor_5_id int,
visitor_5_time timestamp);

Чтобы сохранить посещение, вы должны вставить новую строку с посетителем_1 в качестве посетителя. Для дубликатов вы сдвинете вниз ранее сохраненные значения:

INSERT INTO user_visitors SET ... 
... ON DUPLICATE KEY UPDATE visitor_5_id = visitor_4_id, visitor_5_time = visitor_4_time ...
... visitor_1_id = ?, visitor_1_time = ?

Если вы беспокоитесь о дубликатах, вы можете решить их, добавив IF в раздел UPDATE, чтобы строка не обновлялась, если visitor_id уже присутствует в строке. В коде вы можете проверить наличие обновленного количества строк. Если ноль, обработайте двойное обновление времени посетителя оттуда. Это включает в себя некоторую работу, но это будет быстро и легко понять.

0 голосов
/ 13 января 2010

Если вы заботитесь только о последнем посещении посетителем, а не ВСЕХ посещениях, как насчет использования уникальной пары ключей для идентификатора пользователя / посетителя, а затем использования INSERT INTO .. ​​ON DUPLICATE KEY:

CREATE TABLE uservisitors (... UNIQUE (userid, visitorid) );
INSERT INTO uservisitors (userid, visitorid, time) VALUES (....) ON DUPLICATE KEY UPDATE time=NOW();

Тогда просто выберите пять лучших посетителей:

SELECT visitorid FROM uservisitors WHERE user_id=1 ORDER BY time DESC LIMIT 5;

Нет повторяющихся записей или необходимости группировать по.

0 голосов
/ 12 января 2010

Найти отдельных посетителей за последние 5 минут. Вы можете изменить ИНТЕРВАЛ на любой период времени, например ИНТЕРВАЛ 1 ДЕНЬ, за последние 24 часа.

SELECT distinct visitorid 
FROM uservisitors
WHERE userid = 1 AND time > DATE_SUB(NOW(), INTERVAL 5 MIN);
0 голосов
/ 12 января 2010

Примерно так должно работать:

SELECT visitorid, MAX(time)
FROM uservisitors
WHERE userid = 1
GROUP BY visitorid
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...