Есть несколько таблиц: 1) `country`Содержит название стран и их ключ (id , name) 2) `city` Содержит название городов их ключи и ключи стран (id, name, contryId) 3) `company` Название фирм и ключи фирм (id, name) ... ... n) `car` Таблица товаров (id, name ,countryId, cityId, сompanyId, price, .....) Тужно сделать выборку товаров, где стоимость < 2000$, типа: 1 - Автомобиль - Германия - Берлин - 1999$ Я представляю как это сделать с помощью нескольких запросов: [sql]"SELECT * FROM `car` WHERE `price` < 2000"[/sql] Далее для каждого из результатов узнавать название Страны, города и фирмы [sql]"SELECT `name` FROM `city` WHERE id = .." "SELECT `name` FROM `country` WHERE id = .." "SELECT `name` FROM `company` WHERE id = .." ....[/sql] Ну это, наверное, глупо, так как характеристик товаров у меня больше 10 Возможно ли объединить эти запросы в один? Заранее спасибо за ответ...
[sql]SELECT * FROM table JOIN table1 ON table1.id = table.myTable1Id JOIN table2 ON table2.id = table.myTable2Id ....[/sql] Только поля с одинаковыми именами в разных таблицах необходимо будет перечислить вместо * и указать им алиасы.
Спасибо за пример! Нашел еще один вариант реализации: [sql] SELECT table1.name AS name, table2.name AS name2 ..... FROM `table`, `table1`, `table2`.... WHERE table1.id = table.myTable1Id AND table1.id = table.myTable1Id .... [/sql]
Это просто другая форма синтаксиса JOIN и работает не во всех БД Лучше его записывать явно. Поскольку есть варианты JOIN - LEFT, RIGHT, CROSS, FULL и много других. http://en.wikipedia.org/wiki/Join_(SQL)
Пришел к выводу, что в моем случает соединять таблицы не лучший вариант Строк в главной таблице более 10 млн( > 1 Гб), и обработка запроса занимала около 40сек. Пришлось принимать меры, для начала поменял тип всех значений с главной таблицы на числовой, что привело к созданию парочки дополнительных справочных таблиц. Решил создать 1 запрос, который будет выбирать из базы 10 записей, по условиям, которые задает пользователь [sql] SELECT `val1`, `val2`, .... FROM `table` WHERE `term1`, `term2` ..... LIMIT 0, 10 [/sql] И уже по этим 10 записям делать выборку с остальных таблиц... Результат получился неоднозначным Когда пользователь задает условия, при которых 10 записей находятся быстро, то скорость 2-8 сек. Но если задает такие, записей по которым в таблице < 10, или задает сортировку [sql] ORDER BY `val1` ASC [/sql] то скорость опять поднимается до 40 сек. Существует ли методы в mysql для сокращения работы с таким количеством данных? Единственное, что приходит мне в голову, так это разделить главную таблицу на несколько меньших. И уже в зависимости от параметра, который указывается обязательно мы выбираем таблицу в которой искать, далее применить предыдущий метод...
Сайт туристического агенства. Есть таблица туров (цена, дата вылета, страна, город вылета, город прилета, курорт .....) все по чем будет идти выборка заданы в числовом формате. [sql]CREATE TABLE `tours` ( `P` mediumint(9) NOT NULL, `D` int(11) NOT NULL, `aFCK` mediumint(9) NOT NULL, `aTCK` mediumint(9) NOT NULL, `htlBK` mediumint(9) NOT NULL, `htlK` mediumint(9) NOT NULL, `htlCoK` mediumint(9) NOT NULL, `htlCiK` mediumint(9) NOT NULL, `htlRK` mediumint(9) NOT NULL, `htlCN` text, `htlN` mediumint(9) NOT NULL, `htlD` mediumint(9) NOT NULL, `htlM` mediumint(9) NOT NULL, `roomTK` mediumint(9) NOT NULL, `roomAK` mediumint(9) NOT NULL, `roomNA` mediumint(9) NOT NULL, `roomNC` mediumint(9) NOT NULL, `roomCK` mediumint(9) NOT NULL, `operator` text, `SPO` int(11) NOT NULL, `key` int(11) NOT NULL, PRIMARY KEY (`key`) )[/sql] Количество записей меняется, в зависимости от срока действия, в пределах 9 - 12 млн. туров. Весом где-то 0,9-1,2 Гб Таблицы справочников, где связываются id городов, стран, гостиниц... с их именами. Аналогичные этой: [sql] CREATE TABLE `country` ( `Key` int(11) NOT NULL, `Name` text, `NameLat` text, PRIMARY KEY (`Key`) ) [/sql] Соответственно нужно при заданных параметрах поиска вывести результат. В поиск обязательно включены параметры `Стана` и `Город вылета`, все остальные могут не иметь значений, то есть не возможно задать запрос типа `вывести все туры`. [sql] SELECT `P`, `D`, `htlCoK`, `htlK`, .... FROM `tours` WHERE `aFCK` = $_POST['cityFrom'] AND `htlCoK` = $_POST['country'] ORDER BY `P` ASC LIMIT 0,10 [/sql] Такой вот запрос выполняется около 40 сек Выходя из этого, можно разделить таблицу `tours` на несколько меньших, допустим `tours_egypt`, `tours_turkey`.... или на `tours_city1_to_egypt`, `tours_city2_to_turkey` .... И уже в зависимости от выбранной страны искать в нужной таблице... Думаю это приведет к определенной оптимизации... Есть ли еще способы сократить время выборки?
Сейчас посмотрим. EXPLAIN на запросы делал? И в MySQL что говорят тебе эти два лога? log-slow-queries = D:/Web/mysql_slow_query.log log-queries-not-using-indexes = D:/Web/mysql_query_nui.log
С explain не знаком, поэтому не делал) На счет логов, те, которые вы указали, хостер походу не дает, есть следующие: hardqueries.log mysqlusage.log cpuusing.log
посмотри его. Значит есть повод познакомиться. Делается EXPLAIN тут твой обычный запрос например [sql]EXPLAIN SELECT `P`, `D`, `htlCoK`, `htlK`, .... FROM `tours` WHERE `aFCK` = $_POST['cityFrom'] AND `htlCoK` = $_POST['country'] ORDER BY `P` ASC LIMIT 0,10[/sql] Сейчас, я базу набью, посмотрим что происходит Хотя первое что очевидно сразу это добавить индексы по `aFCK`,`htlCoK`
hardqueries.log Код (Text): DATE: 2010-02-04 11:54:04 PID: 29448 %CPU: 30.2% %MEM: 4.7% VSZ: 307628 kB RSS: 283356 STAT: S TIME: 1:03 SCRIPT: .../update/uploadSPO.php Query String: 0 Remote Address: 188.163.129.248 uploadSPO.php - это скрипт загрузки в БД туров у туроператора. Информации о скрипте, который делает выборку тут нет. EXPLAIN: [sql] id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE tours ALL NULL NULL NULL NULL 10440705 Using where; Using filesort [/sql]
самое нехорошее, что может быть на больших выборках. Начинай тыкать индексы по полям. Добавь два что я сказал и попробуй сделать EXPLAIN для своего запроса опять Зависит от запросов.
Так, ну что я могу сказать. Залил я базу. 15млн записей первые два запрос без индексов 3й и 4й с двумя отдельными индексами по полям aFCK,htlCoK Код (Text): mysql> show profiles; +----------+-------------+---------------------------------------------------------+ | Query_ID | Duration | Query | +----------+-------------+---------------------------------------------------------+ | 1 | 60.47279750 | select * from tours where aFCK = 101 and htlCoK = 102 | | 2 | 62.95918725 | select * from tours where aFCK = -101 and htlCoK = -202 | | 3 | 1.13012300 | select * from tours where aFCK = 101 and htlCoK = 102 | | 4 | 0.88023450 | select * from tours where aFCK = -101 and htlCoK = -202 | +----------+-------------+---------------------------------------------------------+ 4 rows in set (0.00 sec)
Круто, в 60 раз быстрее получается) Спасибо за потраченное время! Индексы установить не удалось, слишком долгий процесс, браузер завершал работу...) Решил перезалить базу туров, уже в несколько таблиц с индексами. Еще раз огромное спасибо)
это делается не через браузер, а через ssh или консоль. у меня индексы ставились примерно 15-20минут. комбинированный все еще ставится вот уже скоро час
Теоретически, если перед навешиванием индекса залочить табличку на запись - будет быстрее. Не уверен, что в мускуле это так, но...
Только что закончил подгрузку туров в новые таблицы с индексами, поиск осуществляется моментально (0,08 сек)
Penegan вообще лучше почитай, как правильно ставить индексы, то есть по каким полям и т.д, чтобы эти вопросы ту уже знал.
Добавка Код (Text): | 5 | 0.66462750 | select * from tours where aFCK = -101 and htlCoK = -202 | | 6 | 0.68352100 | select * from tours where aFCK = 101 and htlCoK = 102 | +----------+-------------+---------------------------------------------------------+ Код (Text): mysql> explain select * from tours where aFCK = -101 and htlCoK = -202; +----+-------------+-------+------+----------------------+----------+---------+-------------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+----------------------+----------+---------+-------------+------+-------+ | 1 | SIMPLE | tours | ref | afck,htlcok,combined | combined | 6 | const,const | 39 | | +----+-------------+-------+------+----------------------+----------+---------+-------------+------+-------+ 1 row in set (0.05 sec) mysql> explain select * from tours where aFCK = 101 and htlCoK = 102; +----+-------------+-------+------+----------------------+----------+---------+-------------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+----------------------+----------+---------+-------------+------+-------+ | 1 | SIMPLE | tours | ref | afck,htlcok,combined | combined | 6 | const,const | 56 | | +----+-------------+-------+------+----------------------+----------+---------+-------------+------+-------+ 1 row in set (0.00 sec) Собственно для данных двух конкретных запросов комбинированный индекс лучше примерно на 60%
Возможно, но проверять мне лень уже Тогда мне не удалось бы снять слепок работы без индексов таблица 15млн записей. в среднем в выборке получается по 300к записей при группировке по 2м полям.