Модераторы: skyboy, MoLeX, Aliance, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Большое число обращений 
:(
    Опции темы
slva2000
Дата 16.4.2010, 12:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 50
Регистрация: 29.10.2005

Репутация: нет
Всего: нет



Доброго дня.


Существует большой массив строк, содержащий WHERE условия запросов. По сути это список файлов (порядка 50 000).

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

Размер таблицы post приблизительно 350 МБ (порядка 440 000 строк).

Пытаюсь делать так:


Код

for($i=0; $i<count($where);$i++)
{
    if ($db->query("SELECT id FROM post WHERE ".$where[$i]."LIMIT 1"))
        echo "ok";
    else
        echo "false";
}


id - некоторое уникальное число в таблице; $db - класс, с методом без закрытия конекта... (хотя суть не в нём...)

В результате, даже при размере массива = 500 записям MYSQL вешается и сваливается с внутренней ошибкой (500).

Как можно оптимизировать этот запрос?
PM MAIL   Вверх
skyboy
Дата 16.4.2010, 13:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 14
Всего: 260



Цитата(slva2000 @  16.4.2010,  11:38 Найти цитируемый пост)
500

mysql или все же apache?
оптимизировать могут посоветовать не запрос, а процесс.
но для этого лучше, чтоб ты привел-таки пример, как у тебя выглядят эти "$where[$i]"(как будет выглядеть сформированный запрос) и как у тебя хранятся имена файлов.
PM MAIL   Вверх
slva2000
Дата 16.4.2010, 13:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 50
Регистрация: 29.10.2005

Репутация: нет
Всего: нет



Цитата

mysql или все же apache?

э.. Я выполняю скрипт на php 5.х, подключаясь к MYSQL... 

Примеры where следующие:
Код

short_story LIKE '%1247852790_fd1bf1679c83c2a107a0fe3c02a10134_beatport.jpg%' OR full_story LIKE '%1247852790_fd1bf1679c83c2a107a0fe3c02a10134_beatport.jpg%'

т.е. я ищу имена файлов в short_story и full_story. Затем:

Код

if ($db->num_rows($row) ==1)
 echo "ok";
else
 echo "false";


Заметил интересную особенность (поставил микротаймер для отладки): если запускаю процесс повторно, то он выполняется в сотни раз быстрее. Если же время выполнения превышает, помоему, 60 сек, - то Internal Error (полагаю MYSQL возвращает ошибку). Тут же F5 (перезапуск скрипта с теме же параметрами - всё прекрасно. Время выполнения - 2 сек. Кол-во итераций: 2518.

Похоже на кэширование, но мне от него не дегче... Впереди 500к файлов...... :(
PM MAIL   Вверх
skyboy
Дата 16.4.2010, 13:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 14
Всего: 260



Цитата(slva2000 @  16.4.2010,  12:16 Найти цитируемый пост)
э.. Я выполняю скрипт на php 5.х, подключаясь к MYSQL... 

что за "ошибка 500"? точнее, где ты её видишь?
в логах апача? в браузере? или же в логе mysql.log написано "Error #500"?

Добавлено через 7 минут и 49 секунд
Цитата(slva2000 @  16.4.2010,  12:16 Найти цитируемый пост)
превышает, помоему, 60 сек, - то Internal Error (полагаю MYSQL возвращает ошибку)

если ты это видишь в браузере, то нет, эту ошибку генерирует Apache. из-за слишком длительного выполнения РНР-скприта, который(скрипт) в свою очередь, ожидает выполнения SQL-запроса. надо отличать одно от другого. это критично.
если видишь ошибки  на экране в окне браузера - это сообщения, сгенерированный Apache или РНР. ошибки mysql можно найти в логе mysql_error.log на сервере, или же вывести в браузер же при помощи функции mysql_error:
Код

$query = mysql_query('SELECT ...... ') || die(mysql_error());

касательно самой процедуры поиска.
лучше отдельно хранить список картинок: имя файла + идентификатор записи в таблице с полем short_story(данные в этой таблице обновлять сразу при вставке записи в "основную таблицу" или по некоему расписанию, скажем, раз в сутки), где хранится упоминание этого файла.
тогда для поиска можно будет использовать не тормознутейший LIKE, а простое сравнение. а само поле с именем файла проиндексировать и поиск будет происходить быстрее на порядок.
вот только зачем сам процесс поиска упоминания файлов? не для того ли, чтоб удалять файлы, на которые нет ссылки? если да, то:
  • дешевле может быть плюнуть на это дело: дисковое пространство намного дешевле процессорного времени(если у тебя выделенный сервер, то проще докупить ещё винт на 500ГБ, чем ежедневно на 5 минут грузить процессор на 100%)
  • при использовании отдельной таблицы со списком упоминаемых файлов(см. выше) можно сразу удалять файлы при удалении "статьи"

PM MAIL   Вверх
awdev
Дата 16.4.2010, 14:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 22.11.2009

Репутация: нет
Всего: 1



мне кажется все таки нужно оптимизировать запрос.

не совсем понял условия про имена файлов, но запросы like '%...%' нежелательны по той простой причине что мускул не использует индексы, а сканирует всю таблицу, отсюда и долгое зависание. Может все же стоит немного изменить структуру или условия хранения, тогда бд будет возвращать быстро все. (~ до 0.1-0.2сек)
Минусы:
 . надо править структуру
 
Второй вариант поступить иначе. И парсить на стороне клиента (рнр), тогда будет "зависать" РНР скрипт.
плюсы: 
 . бд не нагружается так сильно. и может обрабатывать другие запросы быстрей.

Третий вариант: 1 раз написать скрипт который проиндексирует ваши записи.
то есть пройдет по БД по всем записям пост и повытягивает оттуда строки [a-z0-9].(jpg|bmp|gif...) и составит соответствие айдипоста-строка.
Так будет искать быстрее.
плюсы: быстрый поиск
минусы: не реал тайм информация

Выбирайте вариант который более по душе. У каждого есть + и -.


PM MAIL   Вверх
slva2000
Дата 16.4.2010, 14:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 50
Регистрация: 29.10.2005

Репутация: нет
Всего: нет



Ошибка генерируется Апач. Internal S\erver Error (500)

Цитата(skyboy @  16.4.2010,  13:33 Найти цитируемый пост)
 не для того ли, чтоб удалять файлы, на которые нет ссылки? если да, то:

В точку.  Практика показала, что файлов хранится много лишних (из-за неверное работы третьего скрипта ранее) и о них нет упоминания в "текстах"...
 Скрипт пишу на коленке, чтобы запустить раз, вычистить и забыть...

Иметь бОльшее дисковое пространство можно, но хотелось всё же решить проблему в правильном ключе.

Спасибо за ответы, но всё же как лучше быть? Натыкался на mysql_ping() (что то вроде...) может она поможет?

Цитата(awdev @  16.4.2010,  14:09 Найти цитируемый пост)
Может все же стоит немного изменить структуру или условия хранения, тогда бд будет возвращать быстро все. (~ до 0.1-0.2сек)

Как я писал выше - это скрипт без юзер интерфеса и "на раз". Т.е. удалили ненужные файлы и ушли..

Добавлено через 3 минуты и 31 секунду
Вот лог:
[Fri Apr 16 15:27:07 2010] [warn] mod_fcgid: read data timeout in 40 seconds

Добавлено через 8 минут и 24 секунды
В скрипте, разумеется есть строки:
Код

@set_time_limit (0);
@ini_set ('max_execution_time', 0);

PM MAIL   Вверх
slva2000
Дата 16.4.2010, 14:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 50
Регистрация: 29.10.2005

Репутация: нет
Всего: нет



Возникает только такие мысли:

читать директории и имена файлов циклом, и внутри ЭТОГО цикла проверять каждый файл на наличие в БД. Т.о. между запросами будет небольшая пауза.

На настоящие момент я использую новую функцию glob() для получения массива файлов, и уже потом использую массив для поиска по базе.
PM MAIL   Вверх
capitan
Дата 16.4.2010, 19:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 602
Регистрация: 27.2.2005
Где: Москва

Репутация: 2
Всего: 13



А что мешает записать все файлы во временную таблицу и запускать скрипт с LIMIT? У прочеканных файлов выставлять статус  есть \ нет, а потом выбрать все "нет", можно так же через LIMIT если их много, и грохнуть их. И в конце грохнуть временную таблицу. Как то так.
PM MAIL WWW ICQ   Вверх
slva2000
Дата 16.4.2010, 19:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 50
Регистрация: 29.10.2005

Репутация: нет
Всего: нет



capitan
Немного не понял...

Проблемы с созданием списка файлов не существует. Существует проблема циклического построения запросов вида:

Код

SELEST id FROM post WHERE short_story LIKE '%beatport.jpg%' OR full_story LIKE '%beatport.jpg%';


Таких запросов порядка 400к с различными значениями LIKE %%
PM MAIL   Вверх
ksnk
Дата 16.4.2010, 19:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 14
Всего: 386



Цитата(slva2000 @  16.4.2010,  12:38 Найти цитируемый пост)
Существует большой массив строк, содержащий WHERE условия запросов. По сути это список файлов (порядка 50 000).

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

А почему бы не поместить в таблицу все эти 50000 строк и не выяснить кто в каком домике живет единственным запросом?

вероятно, правильным решением будет - перелопатить таблицу с файлами, порезать имя файла на пару частей - собственно имя файла и путь к нему. тогда если поставить имя файла индексированным полем - получим очень приличный бонус по скорости выполнения ;) 
В любом случае - like не самое эффективное по скорости решение для текстового поиска в больших таблицах. 


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
capitan
Дата 16.4.2010, 19:54 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 602
Регистрация: 27.2.2005
Где: Москва

Репутация: 2
Всего: 13



slva2000,  
1. загоняем все файлы в таблицу temp_img   
img | status | check |
img - имя картинки
status - true / false (есть в таблице post или нет)
check - статус проверки true / false ( проверялся в таблице post или нет)

2. Далее запускаем на чек, которые не проверены с лимитом
   SELECT img 
      From temp_img 
      WHERE check = 'false' 
      LIMIT 10

получили список файлов.
3. Проверили на наличие этих файлов в таблице post
4. выставили в temp_img 
check = true
status = true / false (в зависимости от наличия)
5. Повторили 2-4  до тех пор пока есть WHERE check = 'false' 
6. Выбрали из temp_img WHERE status = 'false'  и грохнули их
7. Удалили temp_img

Смысл запускать на проверку пачками , но отмечать уже проверенные. Путей реализаций может быть множество.

ksnk
ТС пояснил, что это одноразовое решение, необходимое для разовой очистки картинок с сервера, которых нет в постах.


Это сообщение отредактировал(а) capitan - 16.4.2010, 19:57
PM MAIL WWW ICQ   Вверх
IgorIV
Дата 16.4.2010, 19:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 642
Регистрация: 7.9.2009

Репутация: нет
Всего: 8



Что имеем: кучу статей с картинками, ещё бОльшую кучу картинок которые не используются.
Что делаем: парсим статьи, ища картинки и заносим их таблицу, поля сам придумаешь. Потом ищем уже в файловой системе ненужные картинки и удаляешь их, вот и всё. 
awdev, уже тебе рассказал как надо.
PM MAIL   Вверх
slva2000
Дата 16.4.2010, 20:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 50
Регистрация: 29.10.2005

Репутация: нет
Всего: нет



ksnk уловил мысль!

Спасибо.

Поправь, если ошибаюсь:

табилца файлов (filelist):

id   path   filename


Запрос:

Код

SELECT fl.id FROM filelist fl, post p WHERE p.short_story LIKE %fl.filename% OR p.full_story LIKE %fl.filename%;


Добавлено @ 20:03
Код

SELECT fl.id FROM filelist fl, post p WHERE p.short_story LIKE % SELECT fl.filename FROM fl WHERE ?% OR p.full_story LIKE % SELECT fl.filename FROM fl WHERE ?%


Помоги пожалуйста... тут я слаб

Добавлено через 13 минут и 36 секунд
пока писал, появились новые посты. Действительно решений предложили несколько...

capitan спасибо. 

IgorIV, немного не так. Ситуация такова: Картинок действительно очень много. Но не используемых не так много. Порядка 3-5%. Статей меньше в 10 раз, чем ратинок. Но объём каждой может достигать 300 кБ.

Цитата(IgorIV @  16.4.2010,  19:54 Найти цитируемый пост)
Потом ищем уже в файловой системе ненужные картинки и удаляешь их, вот и всё. 
 Определяю ненужные проверкой из созданой таблицы с картинками и наличии её в списке существ. файлов?... Сложно выйдет, т.к. парсить статьи придётся с учётом пути до картинки (а их использованно очень много и регуляркой здесь вряд ли обойдёшься, т.к. путь тоже нужно забирать).


Это сообщение отредактировал(а) slva2000 - 16.4.2010, 20:04
PM MAIL   Вверх
capitan
Дата 16.4.2010, 20:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 602
Регистрация: 27.2.2005
Где: Москва

Репутация: 2
Всего: 13



Запрос должен быть примерно таким:
Код

SELECT fl.id, p.id 
   FROM filelist fl
   LEFT JOIN post p ON(p.short_story LIKE %fl.filename% OR p.full_story LIKE %fl.filename%)
   WHERE p.id IS NULL

PM MAIL WWW ICQ   Вверх
Fortop
Дата 16.4.2010, 20:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2200
Регистрация: 13.11.2007
Где: Донецк

Репутация: 3
Всего: 42



Цитата(slva2000 @  16.4.2010,  20:00 Найти цитируемый пост)
 т.к. парсить статьи придётся с учётом пути до картинки (а их использованно очень много и регуляркой здесь вряд ли обойдёшься, т.к. путь тоже нужно забирать).

А надо это не делать постоянно. 
Это делается один единственный раз при добавлении документа.

А правильное решение предложил skyboy, 
Цитата(skyboy @  16.4.2010,  13:33 Найти цитируемый пост)
дешевле может быть плюнуть на это дело: дисковое пространство намного дешевле процессорного времени(если у тебя выделенный сервер, то проще докупить ещё винт на 500ГБ, чем ежедневно на 5 минут грузить процессор на 100%)


Добавлено через 1 минуту и 44 секунды
Цитата(capitan @  16.4.2010,  20:15 Найти цитируемый пост)
p.short_story LIKE %fl.filename% OR p.full_story LIKE %fl.filename%

Жесть вы извращенцы.

запрос может быть только вида
Код

SELECT * FROM `...`
JOIN `...` ON `...`.id = `...`.id


Какие like и зачем?


--------------------
Мир это Я.
Живее всех живых.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Базы Данных | Следующая тема »


 




[ Время генерации скрипта: 0.1231 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.