- Поисковые системы
- Практика оптимизации
- Трафик для сайтов
- Монетизация сайтов
- Сайтостроение
- Социальный Маркетинг
- Общение профессионалов
- Биржа и продажа
- Финансовые объявления
- Работа на постоянной основе
- Сайты - покупка, продажа
- Соцсети: страницы, группы, приложения
- Сайты без доменов
- Трафик, тизерная и баннерная реклама
- Продажа, оценка, регистрация доменов
- Ссылки - обмен, покупка, продажа
- Программы и скрипты
- Размещение статей
- Инфопродукты
- Прочие цифровые товары
- Работа и услуги для вебмастера
- Оптимизация, продвижение и аудит
- Ведение рекламных кампаний
- Услуги в области SMM
- Программирование
- Администрирование серверов и сайтов
- Прокси, ВПН, анонимайзеры, IP
- Платное обучение, вебинары
- Регистрация в каталогах
- Копирайтинг, переводы
- Дизайн
- Usability: консультации и аудит
- Изготовление сайтов
- Наполнение сайтов
- Прочие услуги
- Не про работу
Все что нужно знать о DDоS-атаках грамотному менеджеру
И как реагировать на "пожар", когда неизвестно, где хранятся "огнетушители
Антон Никонов
Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий
Доброго времени суток, уважаемые. Столкнулся с проблемой выборки из MySQL.
Суть вопроса:
нам следует выбрать из бд (поиск идет по полю INT) все значения, начинающиеся к примеру на 18
Такой вопрос можно решить использованием LIKE, т.е. получится что-то вроде
но беда в том, что LIKE использует полный перебор всех строк. А записей более 100 000, а это существенная потеря в скорости и колоссальная нагрузка. Может кто сталкивался с подобной проблемой. Подскажите, как лучше сделать выборку, возможно есть альтернативный вариант без использования LIKE?
Доброго времени суток, уважаемые. Столкнулся с проблемой выборки из MySQL.
Суть вопроса:
нам следует выбрать из бд (поиск идет по полю INT) все значения, начинающиеся к примеру на 18
Такой вопрос можно решить использованием LIKE, т.е. получится что-то вроде
но беда в том, что LIKE использует полный перебор всех строк. А записей более 100 000, а это существенная потеря в скорости и колоссальная нагрузка. Может кто сталкивался с подобной проблемой. Подскажите, как лучше сделать выборку, возможно есть альтернативный вариант без использования LIKE?
Сделайте доп. поле типа tinyint допустим и повесьте на него индекс. Засуньте в него первые 2 символа int-овой строки.
like 18% будет искаться очевидно newint=18
like 1802% будет искаться newint=18 and id like '1802%' (newint=18 отсеет 99 из 100).
like 1% будет искаться как (newint=1 or newint between (10,19) ) and id like '1%' (newint отсеет опять же бОльшую часть).
Или
засуньте эти int-ты в char/varchar строку и повесьте индекс, индекс работает в чар/варчаровых полях как раз по началу строки, только убедитесь что он будет и от 1 срабатывать (по умолчанию вроде от 3 или 4 символов работает).
Если количество первых символов не определено - создайте доп.поля(char1, chars2, chars3, e.t.c) тип - целочисленный, беззнаковый(до 2^32-1)
опять же, если каждый раз требуется выбирать разное количество первых символов, то в своем скрипте определяем необходимое количество первых символов и исходя из этого обращаемся к определенному полю
WHERE `char1`='$var'
WHERE `chars2`='$var'
WHERE `chars3`='$var'
На эти поля делаем индекс.
Смотрим, как уменьшилось время запроса.
Пишим на форум, ибо интересна разница между ДО и ПОСЛЕ:)
ЗЫ. фуллТекстИндекс работает по дефолту от 4 символов. Но можно к примеру писать в БД не 18, а ХХ18, чтобы заставить работать фултекст.
Покажите для примера несколько значений из поля INT, по которому идёт поиск? Мне кажется Вы преувеличиваете масштаб проблемы, там не аж 100 000, а всего 100 000 и запрос очень простой :) Если проект не highload, то можно и без ухищрений обойтись
возможно есть альтернативный вариант без использования LIKE?
Вы всё деревья строите? =) Вложенные множества на индексных колонках работают... Да и запрос where parent = 18 быстрее выполнится..
Да и не обязательно каждый раз всё запрашивать - можно кэширование результатов запроса использовать..
а это существенная потеря в скорости
А в числах? Может действительно
Вы преувеличиваете масштаб проблемы
p.s.
А записей более 100 000
это дерево категорий? =)
ЗЫ. фуллТекстИндекс работает по дефолту от 4 символов.
Настраивается в конфиге мускуля, если прав хватит.. Однако, не уверен, что вариант подходящий, т.к. 18 может быть на 2-м и 3-м месте.. и, если не ошибаюсь, ТС отказался от использования разделителей (т.е. в id лежит что-то вроде 185153)
(т.е. в id лежит что-то вроде 185153)
Думаю именно так там и есть, ТС говорил, что тип данных INT. Поэтому обычный индекс на этот столбец Вам (ТС) в помощь и не парьте мозг :) Уверен запрос будет выполняться доли секунды.
SELECT id FROM `dump` WHERE substr( id, 1, 2 ) = 15
Таблица INNODB 490453 записи, выборка более 8000 строк, время 0.3 секунды на выборку.
Впринципе, если это частый запрос, тогда можно кешировать выборку. Но если данные меняются постоянно, то думаю можно сделать триггер.
Ах, да, хранимые процедуры Вам в помощь. Прирост скорости, хз какой правда, Вам гарантирован.
А если таблица в MyISAM? Сильная потеря в скорости будет?
---------- Добавлено 29.11.2012 в 20:21 ----------
(т.е. в id лежит что-то вроде 185153)
Да, все правильно. Именно такая конструкция планируется
---------- Добавлено 29.11.2012 в 20:27 ----------
Могу показать на примере LIKE
Бывают случаи, когда мы получаем id=182030
Это значит, что в ней отображена вся структура, т.е. id категории 1го уровня это 1, id категории 2го уровня это 1820, а третьего соответственно 182030
При условии, что средствами php мы разбили этот id. Тогда получиться так:
id1=18;
id2=1820;
id3=182030;
SELECT title FROM table WHERE id LIKE '$id{N}%';
Идея в том, что у нас есть к примеру около 100 000 записей. у каждой записи своя категория. И предположим нам нужно извлечь все записи, которые относятся к категории с id=182030;
Для неё предположим мы и должны отрисовать так называемые "хлебные крошки", но чтоб оптимизировать структуру и уменьшить кол-во запросов, мы и делаем что-то подобное, что указал выше.
Второй случай, это когда id=3294
Это значит что тут содержиться категория первого уровня id=32, категория второго уровня id = 3294
Я ранее поднимал похожий топик, изучил много материала, который мне посоветовали, много моментов уяснил по хранению, но как сделать оптимальную выборку - решил спросить у вас. Потому что есть вариант написать хранимую процедуру, но мне кажется, что можно решить и меньшими затратами.
но как сделать оптимальную выборку - решил спросить у вас
Оптимальная с точки зрения MySQL - выбор по ключу (WHERE id IN (xx,xxxx) преобразуется к такому же виду)
(проще всего проверить на реальных данных - сделать замер и оценить результат - есть ли смысл "оптимизировать")
Если есть сомнения - EXPLAIN в помощь
1 SIMPLE my_table range PRIMARY PRIMARY 4 NULL 3 Using where
p.p.s Если смущают лишние строчки кода - их можно оформить как метод класса или как функцию, а в коде использовать что-то вроде