В общем проблема как всегда начинается когда на сайте появляется много данных, да ещё и запросы кривые. Помогаю одному человеку, но, что то застрял на одном запросе. Код (PHP): SELECT SQL_CACHE 9 AS test,N.*, (SELECT NAME FROM news_regions where id = N.id_region) AS region, (SELECT NAME FROM news_category where id = N.id_category) AS category, (SELECT NAME FROM news_sources where id = N.id_source) AS source FROM news_news N WHERE 1=1 AND N.id_category = 2 ORDER BY N.date DESC LIMIT 12600,36; при таком вот запросе выдаёт Отображает строки 0 - 29 (36 всего, запрос занял 3.0455 сек.) что не есть гуд. записей в категории 2 где-то около полутора миллионов, вот и буксует. помогите пожалуйста кто чем может ) PHP, JavaScript, SQL и другой код пишите внутри тегов Код ( (Unknown Language)): [b]php][/b]Тут код[b][/[/b][b]code][/b][/color]
А почему отказались от LEFT JOIN? И в вашем случае кеш наверное лучше использовать не для всего запроса, а для подзапросов. И зачем нужна таблица news_news? Я бы сделал так Код (PHP): SELECT N.*, news_regions.NAME as region, news_category.NAME as category, news_sources.NAME as source FROM N LEFT JOIN news_regions, news_category, news_sources ON (news_regions.id = N.id_region AND news_category.id = N.id_category AND news_sources.id = N.id_source) WHERE 1=1 AND N.id_category = 2 ORDER BY N.date DESC LIMIT 12600,36;
LIMIT 12600,36 — эта штука всегда будет чертовски медленной, особенно когда у тебя есть подзапросы. так устроен движок БД: всякий раз данные запроса будут вычисляться с первой "страницы", только 12600 записей будет промотано вхолостую прежде чем будет выдан ответ. Можно попробовать оптимизировать разбив запрос на два: - первый добывает только news_news.id и использует LIMIT. без подзапросов! также надо постараться чтобы этот запрос использовал индексы. смотреть EXPLAIN и делать выводы. - второй с джойнами куда надо и WHERE id INids) — использует вычисленные в первом запросе айдишники Другая стратегия оптимизации: Переписать запрос так, чтобы он использовал не LIMIT m,n, а только LIMIT n. При этом первая строка "страницы" должны определяться через WHERE. Типа WHERE `date` >= :d
в ней сами новости. кстати ваш запрос выдаёт ошибку ON ссылаясь на эту строку (news_regions.id = N.id_region AND news_cat' at
Смотря когда Вы ее скопировали(Последний раз редактировалось Maputo Пн авг 03, 2015 12:30, всего редактировалось 1 раз.). Там была запятая вместо AND Только из нее почему-то данные не выводятся в исходном запросе... Или весь фокус в такой записи Я, честно, не знаю как это интерпритируется Я может просто с таким не сталкивался, и ли должно это выглядеть так: Код (PHP): FROM news_news AS N или Код (PHP): FROM news_news, N Таблица N вообще существует? Проверил - это эквивалент "as N". Тогда чтоб мой вариант сработал вам нужно добавить nesw_news в строку: Код (PHP): FROM news_news AS N
Maputo немножко поправил ваш запрос но у меня почему то не срабатывает, покажите ваш последний вариант пожалуйста
Код (PHP): SELECT N.*, news_regions.NAME as region, news_category.NAME as category, news_sources.NAME as source FROM news_news AS N LEFT JOIN news_regions, news_category, news_sources ON (news_regions.id = N.id_region AND news_category.id = N.id_category AND news_sources.id = N.id_source) WHERE 1=1 AND N.id_category = 2 ORDER BY N.date DESC LIMIT 12600,36; А вообще не мешало бы выложить структуру таблицы news_news и для начала попробуйте с LIMIT 0,36 А потом
структура. Код (PHP): CREATE TABLE IF NOT EXISTS `news_news` ( `id` int(11) NOT NULL auto_increment, `tid` int(11) NOT NULL default '0', `id_category` int(11) NOT NULL default '0', `id_source` int(11) NOT NULL default '1', `id_region` int(11) NOT NULL default '1', `date` datetime NOT NULL default '0000-00-00 00:00:00', `title` varchar(255) NOT NULL default '', `text` longtext NOT NULL, `link` varchar(255) NOT NULL default '', `image` varchar(255) NOT NULL, `counter` int(11) NOT NULL default '0', `comment` int(11) NOT NULL default '0', `seo_title` varchar(255) NOT NULL, `user_id` int(11) NOT NULL, `poll` int(11) NOT NULL default '0', `hits` int(11) NOT NULL default '0', PRIMARY KEY (`id`), KEY `id_category` (`id_category`), KEY `image` (`image`), KEY `category_image` (`id_category`,`image`), KEY `id_region` (`id_region`), KEY `date` (`date`), KEY `id_source` (`id_source`), KEY `counter` (`counter`), KEY `region_category` (`id_category`,`id_region`), KEY `category_date_source` (`id_category`,`date`,`id_source`), KEY `link` (`link`), KEY `source_region` (`id_source`,`id_region`), KEY `user_id` (`user_id`), KEY `hits` (`hits`), KEY `counter_cat` (`id_category`,`counter`), KEY `hits_cat` (`id_category`,`hits`), KEY `cat_date` (`id_category`,`date`), KEY `region_date` (`id_region`,`date`), KEY `region_category_source_date` (`id_region`,`id_category`,`id_source`), KEY `hits_date` (`hits`,`date`), KEY `cat_reg_date` (`id_category`,`id_region`,`date`), FULLTEXT KEY `FULLTEXT` (`text`,`title`) ) ENGINE=MyISAM DEFAULT CHARSET=cp1251 AUTO_INCREMENT=4116217 ; PHP, JavaScript, SQL и другой код пишите внутри тегов Код ( (Unknown Language)): [b]php][/b]Тут код[b][/[/b][b]code][/b][/color]
Я думаю, если это вынести в отдельную таблицу - обработка будет значительно быстрее производиться (поправьте меня, если я не прав) Код (PHP): `text` longtext NOT NULL, Никогда не использовал этот тип данных, но неужели тут не надо указывать размер поля? Я например для текста использую только CHAR(например 240), если текст больше - режу по пробелам на куски меньшие 240. Вот статейка https://dev.mysql.com/doc/refman/5.6/en/innodb-fulltext-index.html Тут почему-то нет longtext P.S.: Сомневаюсь, что текст новости может превышать 65000 символов и исчисляться в миллионах символов.
Maputo так же как и прежде выдаёт ошибку Код (PHP): #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' news_category, news_sources ON (news_regions.id = N.id_region AND news_categor' at line 3 PHP, JavaScript, SQL и другой код пишите внутри тегов Код ( (Unknown Language)): [b]php][/b]Тут код[b][/[/b][b]code][/b][/color]
А так? Код (PHP): SELECT N.*, news_regions.NAME as region, news_category.NAME as category, news_sources.NAME as source FROM news_news AS N LEFT JOIN (news_regions, news_category, news_sources) ON (N.id_region = news_regions.id AND N.id_category = news_category.id AND N.id_source = news_sources.id) WHERE 1=1 AND N.id_category = 2 ORDER BY N.date DESC LIMIT 12600,36; Кстати, еще для оптимизации поменяйте движок на InnoDB https://www.percona.com/blog/2006/05/29/join-performance-of-myisam-and-innodb/
не, к сожалению ошибка осталась Код (PHP): #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' news_category, news_sources ON (N.id_region = news_regions.id AND N.id_categor' at line 3 PHP, JavaScript, SQL и другой код пишите внутри тегов Код ( (Unknown Language)): [b]php][/b]Тут код[b][/[/b][b]code][/b][/color]
спасибо. сейчас запрос прошёл, но время выполнения осталось таким же Код (Text): Отображает строки 0 - 29 (36 всего, запрос занял 3.0978 сек.)
Код (PHP): select sql_cache n.*, r.`name` region, c.`name` category, s.`name` source from news_news n left join news_regions r on r.id = n.id_region left join news_category c on c.id = n.id_category left join news_sources s where s.id = n.id_source where n.id_category = 2 order by n.id_category desc, n.date desc limit 12600,36 Должно быть: Innodb + индекс (id_category, date) + правильные настройки движка (кеш включён, буфер >= размеру таблиц с индексами). И всё будет "летать". Первый запрос (НЕ из кеша) будет заметно меньше секунды, второй такой же (из кеша) - ~0.001 сек. Когда не из кеша, при первом параметре limit-а 0 (первая страница) запрос будет выполнятся меньше 0.01 сек. По мере роста числа будет стремится ближе к секунде (у меня на ~20 млн. последняя страница считывается ~0.6 сек.) Если не достигнет таких параметров - используйте метод, который подсказал artoodetoo. Т.е. разбейте запрос на два: в первом получаете только ИД, во втором запрашиваете/загружаете данные для этих ИД из всех 4-х таблиц. Это может быть быстрее, за счёт того, что первый запрос будет использовать только индекс. Как-то так...
спасибо, но ксожалению тоже выдаёт ошибку Код (Text): #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where s.id = n.id_source where n.id_category = 2 order by n.id_' at line 5
rustrek, голова Вам дана не только шапку носить Включите мозги и поработайте ими хотя бы чуть-чуть, пару секунд. Неужели не видно, что там опечатка - вместо "on" написано "where"?
да не варит она сейчас, два бессонных дня, да действительно не посмотрел, а просто скопировал и всё ну а по запросу, к сожалению так же - Отображает строки 0 - 29 (36 всего, запрос занял 3.0247 сек.)
Если постараться - можно сделать ровно... Chushkin, а что Вы порекомендуете делать с этим? Код (PHP): `text` longtext NOT NULL,
Если всё сделали так, как я сказал, то ... дурите с вероятностью 99.9%. Или себя или нас. Сделайте дамп таблиц и дайте мне ссылку на скачивание (в личку) - я проверю за сколько выполнится на моём домашнем компе, не поленюсь. Добавлено спустя 4 минуты 49 секунд: "Знаем, плавали!" (с) не мой На некоторое время - да. Но по закону Подлости, всё поедет в самый неподходящий момент. По сути, на небольших таблицах (до 10-30 млн. не имеет смысла извращаться) Тип поля зависит от максимально допустимого размера текста (в байтах). До 8К лучше пользовать "text". и т.д. Но не критично и на скорость влияет мало.