Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Как хранить информацию о посетителях если неизвестено число полей?
 
 автор: Odin Kg   (25.09.2004 в 23:28)   письмо автору
 
 

Мне нужно производить голосование на сайте. Проблема в том, что нужно запретить голосовать по одной теме несколько раз. Я думаю хранить у пользователей в куке идентификатор, который будет определять информацию о них в MySQL. Вопрос в том, как лучше организовать хранение таких данных. Хотелось бы конечно завести под всех пользователей одну таблицу, использовать идентификатор как ключ, и заносить в поля данные. Но я ведь заранее не могу сказать, сколько мне нужно полей (хотя конечно можно выделить штук 50, если кончаться – начать заменять наиболее старые).
Можно сделать по другому – заводить под каждого пользователя отдельную таблицу и делать туда INSERT при каждом голосовании.
Подскажите как проще и быстрее.
И еще большой вопрос, при любом из этих подходов быстро появляются лишние данные, которые уже не нужны, так как пользователь больше не ходит к вам на сайт или у него изменился идентификатор, а вся его база данных без толку хранится. Есть здесь какое-нибудь отработанное простое решение или надо раз в неделю проверять на то, что идентификатор использовался, иначе удалять хранимую под ним информацию.

   
 
 автор: cheops   (26.09.2004 в 09:26)   письмо автору
 
   для: Odin Kg   (25.09.2004 в 23:28)
 

Хм... не нужно изменять число полей таблицы, одной таблицы будет вполне достаточно для хранения информации обо всех посетителях. Столбцы определяют лишь состав записи (структуру информации), сама информация хранится в записях, которых может быть не ограниченное количество. Нужно снабдить первичный ключ атрибутом auto_increment, тогда при добавлении новой записи в таблицу с указанием для него нулевого значения или NULL он будет получать уникальное значение
CREATE TABLE poll_ip (
  id_poll_ip int(10) NOT NULL auto_increment,
  ip text,
  puttime datetime default NULL,
  PRIMARY KEY  (id_poll_ip)
) TYPE=MyISAM;

Тогда для каждого посетителя следует добавлять запись при помощи SQL-оператора INSERT:
INSERT INTO poll_ip VALUES (NULL, "201.45.67.2", NOW());

поле id_poll_ip каждый раз при выполнении этого оператора будет получать уникальное значение, которое можно получить при помощи функции mysql_insert_id()
http://www.softtime.ru/dic/id_dic=116&id_group=2

В таблице будут накапливаться записи, соотвествующие отдельным посетителям,
1, 201.45.67.2, 2004-05-29 00:34:14
2, 62.183.50.164, 2004-05-30 00:34:14
3, 62.76.192.50, 2004-05-30 01:10:40
...
34, 81.1.226.252, 2004-05-30 01:13:55

удалять их следует при помощи оператора DELETE с верменным условием, скрипт производящий удаление лучше привязать к странице сайта, который посещают не часто, но регулярно - это обсуждается по ссылке http://www.softtime.ru/forum/read.php?id_forum=1&id_theme=319&page=1

http://www.softtime.ru/read.php?id_forum=1&id_theme=266

   
 
 автор: LimP   (26.09.2004 в 17:01)   письмо автору
 
   для: cheops   (26.09.2004 в 09:26)
 

конечно,cheops прав,просто воспользуйся контролем ip и все будет окей,так везде делается...голосование более правдивое получается,а то какой-нить псих возьмет и проголосует 100 раз и что,это не мнение народа,а мнение какого-то одного индивида...

   
 
 автор: Odin Kg   (26.09.2004 в 18:54)   письмо автору
 
   для: LimP   (26.09.2004 в 17:01)
 

Так IP ведь назначается провайдером , а на прокси-серверах кажется вообще у всех одинаковый IP. Лучше я запишу к пользователю куке с идентификатором.

   
 
 автор: Odin Kg   (26.09.2004 в 18:51)   письмо автору
 
   для: cheops   (26.09.2004 в 09:26)
 

Спасибо за подробные объяснения.
Вы предлагается складывать все данные для всех пользователей в одну таблицу, т.е для каждого голосования запоминать его код, пользователя и время. Но для чего мне каждый раз проводить поиск в общей куче (это ведь долго), возможно лучше будет для каждого пользователя завести личную таблицу, в которой будет только одно поле - код голосования. К тому же туда легко добавлять новые данные и они будут однозначно относиться к этому пользователю.
Вопрос у меня такой, влияет ли на обработку информации через MySQL количество таблиц в базе? Реально от разделения пользователей по разным таблицам количество расчетов снижается, так как информация становится классифицированной, а обрабатывать ее мне нужно часто.

   
 
 автор: cheops   (26.09.2004 в 19:17)   письмо автору
 
   для: Odin Kg   (26.09.2004 в 18:51)
 

Поиск по первичному ключу выполняется очень быстро, во много раз быстрее чем исполняется код PHP (MySQL написана на C, а код PHP интерпретируется). Создав кучу небольших таблиц вы почти 100% потеряете в скорости (точно не выиграете), так как под каждую таблицу отводится отдельный файл (даже три) - на открытие нескольких файлов времени потребуется больше чем на открытие одного. Поиск по базе осуществляется безумно быстро, так как базы данных для этого и создают. Кроме того, следует отметить, что MySQL - это одна из самых быстрых баз данных. В ней не полностью реализован SQL, но по скрости она точно делает всех (в том числе из за счёт не полной реализации SQL). Её может обогнать в скорости только сетевая или иерархическая база данных (но они сейчас помоему только в банкоматах остались :), ну и конечно работа на прямую с файловой системой. Но, работать с файловой системой нужно на C (PHP со совей интерпретируемостью тут рядом не лежал) - это сейчас запрещено практически на всех хост-серверах, поэтому работа с MySQL - это самый быстрый способ работы с файловой системой, и, если нужна вся её скорость таблица должна быть одна.

PS Вообще, чем меньше таблиц и чем больше операций осуществляется средствами СУБД, тем быстрее всё работает.

   
 
 автор: Odin Kg   (27.09.2004 в 13:06)   письмо автору
 
   для: cheops   (26.09.2004 в 19:17)
 

Насчет скорости поиска – благодарю за объяснения.
Если можно еще раз об организации таблицы учета голосований. Вы предложили такой вариант:
1, 201.45.67.2, 2004-05-29 00:34:14
2, 62.183.50.164, 2004-05-30 00:34:14
3, 62.76.192.50, 2004-05-30 01:10:40
...
34, 81.1.226.252, 2004-05-30 01:13:55
Насколько я понял, эта таблица предназначена для учета голосований только в одном месте, а мне надо голосование типа «Выскажите свое мнение по этой теме», т.е. количество тем заранее не определено и их может быть сколько угодно. Т.е. на один IP (или идентификатор) должно быть запомнено произвольное количество голосований.
Видимо, мне нужна таблица с полями:
А) Кто голосовал
Б) По какой теме
В) Когда
Хотя даже и «Когда» не очень нужно – важен только факт голосования.
Т.е. когда пользователь жмет на голосование я ищу в таблице строчку, в которой поле «Кто голосовал» соответствует пользователю, а поле «По какой теме» соответствует выбранной пользователем теме. Если запись найдена, то значит пользователь уже голосовал по этой теме – запретить повторяться. Я верно рассуждаю? Поле с первичным ключом мне наверное вообще не нужно, ведь при поиске оно не используется – будет только место занимать.
Что мне не нравиться в этом варианте, так это то, что чтобы узнать возможность голосования по одной теме надо просмотреть всю статистику сайта. Чтобы аккуратно вывести страничку пользователю мне нужно будет обратиться к таблице столько раз, сколько тем на отображаемой страничке, а их 10 (тогда там, где голосование уже состоялось, оно не будет предлагаться повторно). Можно конечно обратиться один раз с помощью IN(), но тогда надо сначала сформировать строку аргументов на PHP, а после ответа MySQL сравнить их с номерами тем.

Может вообще накидать статистику к пользователю через куке?

Чистку таблицы мне надо производить раз в неделю, но меня беспокоит, что за неделю там записей может накопиться просто уйма (это конечно идеальная ситуация, если на мой сайт будет кто-то заходить, но с точки зрения дальновидности …)

И еще… А для чего мне вообще в таблице первичный ключ?
Для поиска он совершенно не нужен. Я ведь должен искать все записи с определенным IP или каким-либо идентификатором.

   
 
 автор: glsv (Дизайнер)   (27.09.2004 в 15:47)   письмо автору
 
   для: Odin Kg   (27.09.2004 в 13:06)
 

>Видимо, мне нужна таблица с полями:
А) Кто голосовал
Б) По какой теме

Ну в общем да.
1. Идентификатор голосования и
2. Идентификатор голосовавшего

>И еще… А для чего мне вообще в таблице первичный ключ?
>Для поиска он совершенно не нужен. Я ведь должен искать все записи с определенным IP или каким-либо идентификатором.

Первичный ключ можно назначить на любое поле. Оно и играет роль идентификатора. А нужно оно для ускорения поиска. Поиск по ключевому полю будет значительно быстрее чем по обычному полю.
Таким образом первичным ключом можно сделать и поле IP или поле идентификатор. Только нужно соблюдать одно условие - первичный ключ должен быть уникальным. А его легко сделать если завести под идентификатор отдельное поле со свойством auto_increment. Которое будет гарантировать уникальность значений в поле.

PS: Если униальность значений не нужна, то можно не назначать первичный ключ, а сделать просто ключевое поле.

   
 
 автор: glsv (Дизайнер)   (27.09.2004 в 16:11)   письмо автору
 
   для: Odin Kg   (27.09.2004 в 13:06)
 

>Что мне не нравиться в этом варианте, так это то, что чтобы узнать возможность голосования по одной теме надо просмотреть всю статистику сайта.
Не понял. Почему? Вы делаете только один запрос к таблице.

SELECT * FROM table WHERE IP=$ip and id_poll=$id_poll

Если запрос вернул хоть одну запись, то значит пользователь уже голосовал.

>Чтобы аккуратно вывести страничку пользователю мне нужно будет обратиться к таблице столько раз, сколько тем на отображаемой страничке, а их 10

Ну можно еще вот так:
Вы обращаетесь к таблице голосовавших и запрашиваете все темы, на которые голосовал посетитель. (один запрос). И далее при выводе голосований проверяете не проголосовал ли уже посетитель с данным IP (проверяя наличие идентификатора голосования в результатах выполненного запроса).

>Может вообще накидать статистику к пользователю через куке?
А может хранить в куках идентификатор посетителя?
Минус: У пользователя могут быть запрещены куки. И он может их стереть.

Но когда Вы запретите голосовать только по IP - вы можете "отбросить" большую группу посетителей (по моему). Тех у которых будет одинаковый IP.

   
 
 автор: cheops   (27.09.2004 в 21:08)   письмо автору
 
   для: Odin Kg   (27.09.2004 в 13:06)
 

>Видимо, мне нужна таблица с полями:
>А) Кто голосовал
>Б) По какой теме
>В) Когда
Да по тему можно ввести дополнительное поле INT, которое будет принимать значение первичного ключа из таблицы тем
1, первая тема, 3
2, вторая тема, 56
...
34, последняя тема, 78

Последняя цифра число проголосовавших
>Хотя даже и «Когда» не очень нужно – важен только факт
>голосования.
"Когда" вам понадобится для уничтожения устаревших сообщений, вам вряд ли понадобится статистика по IP-адресам за прошедший месяц, так как сам факт голосования можно учитывать увеличивая лишь последнее поле в таблице с темами. Человек, который не смог проголосовать в течении длительного времени уже не будет пытаться сделать это по новой - люди слишком ленивы и у них полно своих дел, чтобы пытаться искать обходные пути для решения проблем, которое не приности им никакой выгоды. Кроме того, это поле много места не занимает - это просто число секунд с 1970 года (поле INT - 1 байт на запись).
>столько раз, сколько тем на отображаемой страничке, а их 10
Вовсе нет, вы можете воспользоваться оператором SQL - GROUP BY для группирования результатов, можете запросить только конкретный IP-адрес - в этом плане базы очень гибки...

>Может вообще накидать статистику к пользователю через куке?
С куками осторожнее, с ними посетители очень любят возится, так как они расположены на их машине - они считают их своей собственностью, а своих долгом сделать всё возможное, чтобы через них у вас было как можно больше проблем :)))
>Чистку таблицы мне надо производить раз в неделю, но меня
>беспокоит, что за неделю там записей может накопиться просто
>уйма (это конечно идеальная ситуация, если на мой сайт будет
>кто-то заходить, но с точки зрения дальновидности …)
У нас посещаемость 2500 хостов в неделю (не голосующих, а просто приходящих на сайт) - при такой базе данных это 150 Кб, поверьте у вас скорее всего долго не будет никаких проблем в этом плане.

>И еще… А для чего мне вообще в таблице первичный ключ?
>Для поиска он совершенно не нужен. Я ведь должен искать все
>записи с определенным IP или каким-либо идентификатором.
Вам было нужно уникальное значение - это идеальный кондидат, так как первичный ключ всегда уникален.

   
 
 автор: Odin Kg   (29.09.2004 в 23:16)   письмо автору
 
   для: cheops   (27.09.2004 в 21:08)
 

Спасибо за помощь.
Основываясь на советах я создал подходящий для моих нужд вариант. Еще пара вопросов:
Мне казалось, что если после вызова SELECT нет ни одной выбранной строки, то результат = 0, однако почему-то при применении SELECT к пустой таблице возвращался какой-то результат, правда, mysql_num_rows($result) был равен 0. Т.е. строки найдены не были. Я что-то не так понимаю?
Ключевое поле – это KEY? И оно может быть не уникальным?
Я хотел бы набить данные в таблицу дома, а потом закинуть их в Интернет. А как перекидывать информацию между MySQL-серверами?

   
 
 автор: cheops   (29.09.2004 в 23:52)   письмо автору
 
   для: Odin Kg   (29.09.2004 в 23:16)
 

1) mysql_query() возвращает дескриптор результата если запрос верен, и false если имеется ошибка в синтаксисе. Т.е. если запрос синтаксически верный, но результат пустой, то дескриптор тоже будет возвращён. Проверка на пустоту запроса осуществляется именно при помощи функции mysql_num_rows() - равно число возвращённых строк нулю или нет.

   
 
 автор: cheops   (29.09.2004 в 23:56)   письмо автору
 
   для: Odin Kg   (29.09.2004 в 23:16)
 

>Ключевое поле – это KEY? И оно может быть не уникальным?
2) Лучше придерживаться "индекс" - этот термин более точно отражает суть. Да, индекс может быть и не уникальным, для того, чтобы сделать его уникальным следует воспользоваться ключевым словом UNIQUE

   
 
 автор: cheops   (30.09.2004 в 00:11)   письмо автору
 
   для: Odin Kg   (29.09.2004 в 23:16)
 

>Я хотел бы набить данные в таблицу дома, а потом закинуть их
>в Интернет. А как перекидывать информацию между
>MySQL-серверами?
3) Это зависит от того, насколько вы вхожи на сервер. Если вам доступна директория с базами данных, можно просто перекачать директорию соотвествующую вашей базе данных, которая расположена в mysql/data/ (имена директорий совпадают с именами баз данных).
Обычно это не так. Поэтому базу данных переводят в текстовый формат при помощи утилиты mysqldump, которая поставляется вместе с дистрибутивом и находится в mysql/bin. Допустим у нас имеется база данных base, тогда дамп базы данных можно получить при помощи команды:
mysqldump base>base.sql

В файле base.sql будут SQL-операторы, позволяющие полностью воссоздать базу данных: для каждой таблицы операторы CREATE, а для каждой записи операторы INSERT.
Если вы имеете SSH или Telnet-доступ к серверу, можно забросить этот файл на сервер и восстановить базу (предварительно её нужно создать) при помощи команды:
mysql base<base.sql

Обычно это не доступно, а для управления базами данных предоставляется панель управления - phpMyAdmin, выбрав в которой меню SQL - в текстовое поле можно поместить содержимое файла base.sql.
Наконец, может не быть ничего кроме FTP, в этом случае дамп нужно преобразовать в PHP-скрипт:
<?php
  $query
[] = "INSERT...";
  
$query[] = "INSERT...";
  
$query[] = "INSERT...";
  foreach(
$query as $val)
  {
    
mysql_query($val);
  }
?>

и выполнить его.

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования