Необычная оптимизация

BelStudent

целеустремлённый чел
Необычная оптимизация

Даже трудно сформировать вопрос одним предложением, поэтому предыстория.
Есть сайт, на сайте поиск. Поиск обрабатывает большое количество информации из БД прежде чем выдать ответ, поэтому довольно длителен. Запросы в поиск подаются однотипные, поэтому я решил оптимизировать систему. Я сохраняю сразу html-страницу с результатом, а сам запрос сохраняю в БД. При повторном поиске просматриваю БД на наличие запроса, если запрос был, то возвращаю уже сгенерированную страницу, если нет - то запускаю все процессы поиска.
Теперь собственно проблема: если 2 человека нажали одновременно кнопку поиска, с абсолютно одинаковыми запросами, то происходит следующее. Скрипт проверяет наличие запроса в БД, его нет и 2 сценария одновременно сохраняют в кеш одинаковые страницы, а главное ДОБАВЛЯЮТ в БД одинаковые запросы. И если придёт новый пользователь и введёт этот запрос, то скрипт находит 2 соответствия в БД. Конечно вы скажите, что выдавай первый результат и всё. НО, представьте если одновременно нажмёт поиск 100 человек, то сгенерится 100 html-страниц (что не столь важно) и добавиться 100 абсолютно одинаковых запросов (что посерьёзнее). Так как добиться того чтобы был записан 1 запрос и сгенерирована 1-а страница при одновременном нажатии на кнопку при одинаковых запросах?

P.s. не интересуют ответы типа: да у тебя такого нигода не будет, что за сайт с такой посещаемосью. Отвечать только по делу.
 

DiMA

php.spb.ru
Команда форума
> P.s. не интересуют ответы типа

тут тоже никого не интересуют твои интимные проблемы и мысли

> Отвечать только по делу.

а указания засунь в одно место (еще хоть слово не по делу - и идем в корзину)

По вопросу. При сохранении кеша нужно сделать примари кей. Либо по всей строке запроса, либо по хешу от строки (md5 -> взять первые 64 бита и засунуть в поле BIGINT, чтобы примари кей был строкой). Да, в один момент кеш по уникальному номеру будет перезаписан много раз, но запись будет одна.

Интересно, что тут не обычного? Тривиальщина...
 

BelStudent

целеустремлённый чел
Спасибо.

P.s. Я PHP занимаюсь не с 99 года как ты, так что для меня это было не тривиально.
P.p.s. Зачем было флудить в ответ на мой постскриптум? Я просто хотел как раз таки избавиться от флуда.
 

pilot911

Новичок
вопрос тривиальный - делать в таблицу вставку поискового запроса сразу, а ответ - после формирования...

в итоге, оба запроса будут лишь формировать ответ.. + можно в скрипте запроса сделать задержку, установив флаг в той же таблице, что ответ формируется, во втором запросе проверять, допустим, через 200 мсек, если ответ не сформирован - то формировать самостоятельно
 

BelStudent

целеустремлённый чел
2 сопутствующих вопроса:
1) есть линк на хороший мануал как работать с битами в PHP
2) как создать переменную-число в PHP в 8 байт?
 

DiMA

php.spb.ru
Команда форума
1) не тупи, ман один. Там все есть. Так же, как в С.
2) в пхп нет типов, как хочешь, так и создавай. Вопрос задавай - как применить переменную.

чтобы из md5 записать в BIGINT биты не нужны, достаточно substr

update set x=0x1122334455667788
 

BelStudent

целеустремлённый чел
Неясно как ты строку привёл к шестнадцатиричному виду?
Попробывал
Код:
base_convert($myString,10,16)
думал, что как в С каждый элемент строки будет расматриваться числом в 1 байт и всё удачно конвертнётся, но ошибался, не прокатило.

И ещё, а каким способом ты сохранял ответ твоего скрипта? Я думаю сделать ещё один скрипт, который будет вызывать первый через
file_get_contents(firstScript.php), а результат уже сохранять в html файл. Ну, можно ещё через CURL, но по-мойму это избыточно.
 

DiMA

php.spb.ru
Команда форума
> Неясно как ты строку привёл к шестнадцатиричному виду?

echo md5(microtime()) и подумай головой
когда осенит - примени substr (чтобы откусить 64 бита, т.е. 8 первых символов) и засунь результат в SQL запрос

вместо microtime() - поисковая строка

если ты в программировании совсем никакущий, есть вариант проще:
заведи словарную таблицу из 2х полей (id, text) и храни там все поисковые фразы
ид и будет твоим уникальным идентификатором
если юзер пишет старую поисковую фразу - вытаскиваешь ранее созданный по AUTOINCREMENT ид'шник
 

BelStudent

целеустремлённый чел
Отвечу по порядку
1) я то отсек 8 байт,
и пишу следующее:
INSERT INTO `cache` (`ID`) VALUES ($b)
где $b содержит нужные 8 байт хеша
но sql запрос возвращает ошибку.
В debuge смотрю запрос и вижу:
При запросе без кавычек:
INSERT INTO `cache` (`ID`) VALUES (2eac2a8a)
Выдаёт
1054Unknown column '2eac2a8a' in 'field list'

При запросе с кавычками
INSERT INTO `cache` (`ID`) VALUES ('2eac2a8a')
выдаёт
1265Data truncated for column 'ID' at row 1

Собствеено всё верно: без кавычек могут передоваться только числа, с кавычками - строки, но у нас тип BIGINT (числовой) поэтому ошибки. Я не понимаю как указать SQL парсеру, что $b лишь ссылка на числовой объект 8-ми байтовой величины.

2) твой вариант, что с полем text, будет работать намного медленнее чем работа с BIGINT, поэтому не одобряю. Хотя в случае с md5 есть вероятность того, что у разных запросов будут одинаквые первые 8 байт, и поэтому может вернуть результат не адекватный запросу.
 

DiMA

php.spb.ru
Команда форума
1) перечитай мое второе сообщение очень внимательно, каждый символ. Или документацию MySQL, как вставляют числа в запросы (без заморочки с битами).

2) я же говорил, куда засунуть "одобряю"? :) Делаешь, как сказано. По скорости - одинаково. С мд5 Вероятность 1 к 18446744073709552000.
 

BelStudent

целеустремлённый чел
Ё-моё. А зачем, блин, шарадами говорить. Сказал бы просто ставь "0x" перед переменной
или для тебя выражение типа "0x$b" тоже тривиально? Ни Java, ни в С++, такого никогда не видел.

P.s. а вообще Спасибо.
 

BelStudent

целеустремлённый чел
Не поверишь, Sphinx я использую. Но по-мойму cache ускорит даже работу Sphinx'a.
 
Сверху