Задавайте вопросы, мы ответим
Вы не зашли.
Страниц: 1 2
Привет всем!
Нужно оптимизировать таблицу и запросы к ней. Суть проблемы в следующем: Таблица прайсов. По ней ищутся запчасти за критерием номер запчасти и название запчасти. Таблица содержит огромное кол-во строк свыше 5 мил.
в переменной $kod содержится код запчасти.
В скриншотах отправляю структуру и содержание самой таблицы.
Есть запрос:
$query = mysql_query("SELECT
prices.marka as marka,
prices.numberKatalog as numberKatalog,
prices.nomenklatura as nomenklatura,
prices.price as price,
prices.presence as presence,
prices.deliveryDate as deliveryDate,
prices.idUser as idUser,
users.sitename as sitename,
users.company as company
FROM
prices,
users,
pricesTested
WHERE
prices.numberKatalog LIKE '$kod%' and
prices.idUser = users.id_USER and
prices.idUser = pricesTested.idUser and
pricesTested.tested = 1
LIMIT $start,$itemsperpage");
Этот запрос на выборку работает но очень медленно! Может кто-либо из Вас сможет подрихтовать саму таблицу (индексы, типы полей и прочие), а также содержание самого запроса!
Буду признателен за любую помощь! Спасибо!
Отредактированно yuriy (11.04.2011 16:01:55)
Неактивен
yuriy написал:
Этот запрос на выборку работает но очень медленно! Может кто-либо из Вас сможет подрихтовать саму таблицу (индексы, типы полей и прочие), а также содержание самого запроса!
Ну для начала нужно знать какие у вас индексы, типы полей и прочее
Покажите результат show create table `имя таблицы`; для всех 3ех использующихся таблиц, а также explain ваш запрос;
И почему у вас код запчасти ищется через like, а не через равенство?
Неактивен
Для табл. prices:
CREATE TABLE `prices` (\n `id` int(11) NOT NULL auto_increment,\n `number` int(11) default NULL,\n `marka` varchar(100) default NULL,\n `numberKatalog` varchar(100) default NULL,\n `nomenklatura` text,\n `amount` int(20) default NULL,\n `price` float default NULL,\n `presence` char(100) default NULL,\n `deliveryDate` char(100) NOT NULL,\n `idUser` smallint(20) default '0',\n PRIMARY KEY (`id`),\n KEY `idUser` (`idUser`),\n KEY `number` (`marka`(20),`numberKatalog`(20),`nomenklatura`(30))\n) ENGINE=MyISAM AUTO_INCREMENT=4242222 DEFAULT CHARSET=cp1251
Для табл. users:
CREATE TABLE `users` (\n `id_USER` int(11) NOT NULL auto_increment,\n `name` varchar(50) NOT NULL,\n `company` varchar(50) NOT NULL,\n `region` int(10) NOT NULL,\n `lawyeradres` varchar(150) default NULL,\n `email` varchar(30) NOT NULL,\n `pass` varchar(20) NOT NULL,\n `passagein` varchar(20) NOT NULL,\n `phone` varchar(40) NOT NULL,\n `phoneother` varchar(40) NOT NULL,\n `sitename` varchar(30) NOT NULL,\n PRIMARY KEY (`id_USER`),\n KEY `email` (`email`)\n) ENGINE=MyISAM AUTO_INCREMENT=655 DEFAULT CHARSET=cp1251
Для табл. pricesTested
CREATE TABLE `pricesTested` (\n `id` int(11) NOT NULL auto_increment,\n `idUser` int(11) NOT NULL,\n `tested` int(11) NOT NULL default '0',\n PRIMARY KEY (`id`),\n UNIQUE KEY `idUser` (`idUser`),\n KEY `tested` (`tested`)\n) ENGINE=MyISAM AUTO_INCREMENT=29 DEFAULT CHARSET=cp1251
explain запрос в скриншоте!
like - использую потому что поиск может быть к примеру по трьом первым цыфрам или буквам тоисть чтобы не было четкой привязки (к примеру пользователь ввел 156FG ему выдаст весть перечень товаров которые начинаются на это значение)
Неактивен
А если искать не по первой букве, а по 3ем первым, explain такой же будет ?
Неактивен
Попробуйте ANALYZE TABLE http://dev.mysql.com/doc/refman/5.5/en/ … table.html
а то у вас, что для 1го, что для 3ех символов результат одинаковый.
Проблема в том, что по like у вас выбирается больше сотни тысяч строк. Очевидно, что пользователю столько не нужно.
Можно, если пользователь вводит не полный код, а первые символы, использовать не указанный запрос, а другой - сначала выбирать из prices первые несколько десятков id, соответствующих указанному коду, а по ним уже выбирать всё остальное.
Неактивен
Так что Вы мне предлагаете: вместо LIKE использовать другой оператор сопоставления? Какой?
Можно, если пользователь вводит не полный код, а первые символы, использовать не указанный запрос, а другой - сначала выбирать из prices первые несколько десятков id, соответствующих указанному коду, а по ним уже выбирать всё остальное. - объясните поподробней, плиз!!!
Неактивен
Погарячился я, так просто не получиться
Тогда так:
Если пользователь вводит полный код - вы используете свой запрос, заменив like на равенство.
Если пользователь вводит почти полный код (без нескольких последних символов), который даст разумное число совпадений - вы используете свой запрос с like.
Если пользователь вводит не полный код, а первые символы, то вы сначала используете доп таблицу, в которой у вас храниться id из прайса, код и ключи на первый символ кода, первые два символа и т.д. По этой таблице, зная первые несколько символов кода, вы выбираете нужное вам число id.
Затем ищите нужную вам информацию из трех таблиц по найденным в предыдущем запросе id.
Неактивен
А как мне узнать что вписал пользователь для критерия поиска: (полный код или почти полный или не полній - всего 3 символа)??? И что такое дополнительная таблица и как ее формировать?
Неактивен
yuriy написал:
А как мне узнать что вписал пользователь для критерия поиска: (полный код или почти полный или не полній - всего 3 символа)???
Откуда-то у вас берется переменная $kod, вот там и анализировать сколько символов ввел пользователь.
yuriy написал:
И что такое дополнительная таблица и как ее формировать?
Обычная таблица,которую вы ввели дополнительно к имеющимся, чтобы оптимизировать выполнение своего запроса. С помощью create table
Неактивен
vasya написал:
yuriy написал:
А как мне узнать что вписал пользователь для критерия поиска: (полный код или почти полный или не полній - всего 3 символа)???
Откуда-то у вас берется переменная $kod, вот там и анализировать сколько символов ввел пользователь.
yuriy написал:
И что такое дополнительная таблица и как ее формировать?
Обычная таблица,которую вы ввели дополнительно к имеющимся, чтобы оптимизировать выполнение своего запроса. С помощью create table
Код запчасти может сосотоять из 5, 10, 15 ( к примеру 1102-565656, 110221 - 5400011, XVV65041301 и т.д.) символов, и наверника точно знать соответствие полного наименования - невозможно. Проанализировать переменную $kod можно, а вот определить соответствует ли она полному названию или частичному - невозможно!!! Поэтому сдесь нужен какой-то другой метод опредиления...
Неактивен
Так больше нет никаких предожений чтобы оптимизировать даный запрос?
Неактивен
Добавьте индекс на `numberKatalog`
alter table `prices` add index(`numberKatalog`);
Неактивен
Добавил! Ну а как и запросом поступать? Нужно в нем избавлятся о LIKE?
Неактивен
что теперь показывает explain?
Неактивен
yuriy написал:
Вот индексы установлены для полей! (скриншот)
Что-то я не вижу здесь индекса на `numberKatalog`
Что показывает
show create table `prices`;
Неактивен
CREATE TABLE `prices` (\n `id` int(11) NOT NULL auto_increment,\n `number` int(11) default NULL,\n `marka` varchar(100) default NULL,\n `numberKatalog` varchar(100) default NULL,\n `nomenklatura` text,\n `amount` int(20) default NULL,\n `price` float default NULL,\n `presence` char(100) default NULL,\n `deliveryDate` char(100) NOT NULL,\n `idUser` smallint(20) default '0',\n PRIMARY KEY (`id`),\n KEY `idUser` (`idUser`),\n KEY `number` (`marka`(20),`numberKatalog`(20),`nomenklatura`(30))\n) ENGINE=MyISAM AUTO_INCREMENT=4242222 DEFAULT CHARSET=cp1251
Неактивен
Вот последнее:
CREATE TABLE `prices` (\n `id` int(11) NOT NULL auto_increment,\n `number` int(11) default NULL,\n `marka` varchar(100) default NULL,\n `numberKatalog` varchar(100) default NULL,\n `nomenklatura` text,\n `amount` int(20) default NULL,\n `price` float default NULL,\n `presence` char(100) default NULL,\n `deliveryDate` char(100) NOT NULL,\n `idUser` smallint(20) default '0',\n PRIMARY KEY (`id`),\n KEY `idUser` (`idUser`),\n KEY `number` (`marka`(20),`numberKatalog`(20),`nomenklatura`(30)),\n KEY `numberKatalog` (`numberKatalog`)\n) ENGINE=MyISAM AUTO_INCREMENT=4242222 DEFAULT CHARSET=cp1251
Неактивен
А последний explain был старый или новый?
Неактивен
Хорошо, пойдем другим путем. Сколько будет
select count(*) from prices where numberKatalog like'A%';
Неактивен
1013859
Неактивен
Страниц: 1 2