помогите сделать грамотный запрос

Wicked

Новичок
1) после осуществления выборки результатов запроса, собери все id необходимых 10-20 туров в один массив, id отелей - в другой. Далее выбери их двумя отдельными запросами с условиями where id in (...10-20 id...) и запихай их в массивы $hotels и $tours с id в качестве ключей. При выводе получай имена отелей/туров по их id из этих массивов.

2) что мешает добавить еще 2 джоина, чтобы выбирать и имена тоже?
 

dimagolov

Новичок
зачем тебе SQL_CALC_FOUND_ROWS? просто при SQL_CALC_FOUND_ROWS LIMIT теряет смысл.
 

Fortop

Новичок
SQL_CALC_FOUND_ROWS подсчитывает число записей невзирая на LIMIT

Но число возвращаемых записей таки обрезаются лимитом.
 

dimagolov

Новичок
zerkms, да musicant задал вопрос, а потом стер его. вопрос был про то, почему добавление LIMIT 0,10 в запрос с SQL_CALC_FOUND_ROWS приводит к получению пустого результата.
 

musicant

Новичок
Странно получилось.
Я стер вопрос, т.к. ответов небыло и я решил , что вы сочли вопрос совсем глупым.
На тот момент ответов небыло, а сейчас их уже 3...
Сорри

P.S.
А вопрос решил так - http://php-developer.ru/category/mysql/
 

Вурдалак

Продвинутый новичок
Автор оригинала: dimagolov
при SQL_CALC_FOUND_ROWS LIMIT теряет смысл.
— наоборот.

-~{}~ 23.02.10 00:14:

Кстати, то ли я чего-то не понимаю, то ли SQL_CALC_FOUND_ROWS — говно.

Почему запрос с ним так долго выполняется? В 10 раз лучше выполнить 2 запроса (один с COUNT(*), другой — «обычный»). К тому же в последнем случае можно ограничить слишком большой номер страницы (я обычно выдаю последнюю страницу).
 

Вурдалак

Продвинутый новичок
Я и сам вижу, какое время. У меня ещё хуже (больше секунды при 100K записей). Вопрос: почему?
 

Fortop

Новичок
Ерунду вы смотрите.

Во-первых COUNT(*) берется из метаданных
Во-вторых, 15к записей не играют никакой роли, это как рулетка, попала выборка в кеш или нет.

К тому же в последнем случае можно ограничить слишком большой номер страницы
Мысли не понял вовсе.
 

zerkms

TDD infected
Команда форума
Fortop
1. не всегда и не у всех myisam
2. выбирают они с where, подозреваю

:)
 

Mr_Max

Первый класс. Зимние каникулы ^_^
Команда форума
Странно, мне хватает вот этого.
PHP:
$sql = "SELECT Price FROM tbl WHERE 1 ";

if($hotel_id !=""){
    $sql .=" AND Hotel_id='$hotel_id' ";
}
-~{}~ 23.02.10 11:24:

упс.
Втыкнул с датой поста.
Сори.
 

Fortop

Новичок
1. не всегда и не у всех myisam
А тогда COUNT(*) не должен быть быстрее.
Впрочем, как освоюсь со свежепоставленным - проверю, где-то у меня была БД на 15млн записей.
 

Вурдалак

Продвинутый новичок
Автор оригинала: Fortop
Мысли не понял вовсе.
— если ввести заведомо несуществующий номер страницы (больше реального количества), то я выдаю последнюю страницу. Заранее же узнать какой LIMIT подставить в запрос с SQL_CALC_FOUND_ROWS узнать нельзя.

Автор оригинала: Fortop
Во-вторых, 15к записей не играют никакой роли, это как рулетка, попала выборка в кеш или нет.
— выборки не из всех таблиц подлежат кешированию. Если таблица постоянно обновляется, то в кешировании смысла нет.

-~{}~ 23.02.10 13:40:

Автор оригинала: zerkms
2. выбирают они с where, подозреваю
— да, естественно. В подавляющем большинстве случаев нужен WHERE, поэтому этой оптимизации не видно.

-~{}~ 23.02.10 13:46:

И всё-таки: получается, что SQL_CALC_FOUND_ROWS — говно?
 

Fortop

Новичок
Автор оригинала: Вурдалак
— если ввести заведомо несуществующий номер страницы (больше реального количества), то я выдаю последнюю страницу. Заранее же узнать какой LIMIT подставить в запрос с SQL_CALC_FOUND_ROWS узнать нельзя.
С этим согласен.
Хотя возврат сообщения - "страница вне диапазона" - вполне решение. Раз уж пользователь такой умный, что вводит несуществующие номера страниц.

Автор оригинала: Вурдалак
— выборки не из всех таблиц подлежат кешированию. Если таблица постоянно обновляется, то в кешировании смысла нет.
-~{}~ 23.02.10 13:46:
Я вообще-то говорил о кеше mysql.
Но почему нет? Или таблица обновляется ВСЯ целиком?

Автор оригинала: Вурдалак
И всё-таки: получается, что SQL_CALC_FOUND_ROWS — говно?
Добрался я таки до базы...

15млн записей. При выборке по двум полям возвращается от 30 до 90 записей

Без индексов
Код:
mysql> show profiles;
+----------+-------------+-----------------------------------------------------------------------------+
| Query_ID | Duration    | Query                                                                       |
+----------+-------------+-----------------------------------------------------------------------------+
|        1 | 22.11624000 | select * from tours where aFCK = -101 and htlCoK = -202                     |
|        2 | 21.81856400 | select sql_calc_found_rows * from tours where aFCK = -101 and htlCoK = -202 |
|        3 |  0.02533200 | select found_rows()                                                         |
|        4 |  8.07275200 | select count(*) from tours where aFCK = -101 and htlCoK = -202              |
+----------+-------------+-----------------------------------------------------------------------------+
4 rows in set (0.00 sec)
С индексами по 2м полям aFCK, htlCoK
Код:
mysql> show profiles;
+----------+------------+------------------------------------------------------------------------------------------+
| Query_ID | Duration   | Query                                                                                    |
+----------+------------+------------------------------------------------------------------------------------------+
|       14 | 0.25131400 | select sql_no_cache count(*) from tours where aFCK = -102 and htlCoK = -201              |
|       15 | 0.21732100 | select sql_no_cache * from tours where aFCK = -102 and htlCoK = -201                     |
|       16 | 0.02705800 | select sql_no_cache sql_calc_found_rows * from tours where aFCK = -102 and htlCoK = -201 |
|       17 | 0.00026900 | select sql_no_cache found_rows()                                                         |
|       18 | 0.02203900 | select sql_no_cache count(*) from tours where aFCK = -102 and htlCoK = -201              |
|       19 | 0.02309600 | select sql_no_cache sql_calc_found_rows * from tours where aFCK = -102 and htlCoK = -201 |
|       20 | 0.00010700 | select sql_no_cache found_rows()                                                         |
|       21 | 0.00010800 | select sql_no_cache found_rows()                                                         |
|       22 | 0.02371500 | select sql_no_cache sql_calc_found_rows * from tours where aFCK = -102 and htlCoK = -201 |
|       23 | 0.33617400 | select sql_no_cache sql_calc_found_rows * from tours where aFCK = -103 and htlCoK = -203 |
|       24 | 0.00022900 | select sql_no_cache found_rows()                                                         |
|       25 | 0.02457000 | select sql_no_cache * from tours where aFCK = -103 and htlCoK = -203                     |
|       26 | 0.02254700 | select sql_no_cache count(*) from tours where aFCK = -103 and htlCoK = -203              |
|       27 | 0.02316000 | select sql_no_cache sql_calc_found_rows * from tours where aFCK = -103 and htlCoK = -203 |
|       28 | 0.00026800 | select sql_no_cache found_rows()                                                         |
+----------+------------+------------------------------------------------------------------------------------------+
15 rows in set (0.00 sec)
Обращаю внимание на то, что хотя указывается SQL_NO_CACHE
первый запрос по условию всегда много дольше последующих
Код:
mysql> show profiles;
+----------+-------------+------------------------------------------------------------------------------------------+
| Query_ID | Duration    | Query                                                                                    |
+----------+-------------+------------------------------------------------------------------------------------------+
|       26 |  0.02254700 | select sql_no_cache count(*) from tours where aFCK = -103 and htlCoK = -203              |
|       27 |  0.02316000 | select sql_no_cache sql_calc_found_rows * from tours where aFCK = -103 and htlCoK = -203 |
|       28 |  0.00026800 | select sql_no_cache found_rows()                                                         |
|       29 | 30.71694900 | select sql_no_cache sql_calc_found_rows * from tours limit 15000001, 10                  |
|       30 |  0.00010700 | select found_rows()                                                                      |
|       31 |  0.23293200 | select SQL_NO_CACHE sql_calc_found_rows * from tours where aFCK = -104 and htlCoK = 203  |
|       32 |  0.00010900 | select SQL_NO_CACHE found_rows()                                                         |
|       33 |  0.02204100 | select SQL_NO_CACHE * from tours where aFCK = -104 and htlCoK = 203                      |
|       34 |  0.10406100 | select SQL_NO_CACHE * from tours where aFCK = -104 and htlCoK = 204                      |
|       35 |  0.02537700 | select SQL_NO_CACHE * from tours where aFCK = -104 and htlCoK = 203                      |
|       36 |  0.02523600 | select SQL_NO_CACHE COUNT(*) from tours where aFCK = -104 and htlCoK = 203               |
|       37 |  0.13862100 | select SQL_NO_CACHE * from tours where aFCK = -204 and htlCoK = 203                      |
|       38 |  0.02486600 | select SQL_NO_CACHE COUNT(*) from tours where aFCK = -204 and htlCoK = 203               |
|       39 |  0.02602100 | select SQL_NO_CACHE SQL_CALC_FOUND_ROWS * from tours where aFCK = -204 and htlCoK = 203  |
|       40 |  0.00026700 | select found_rows()                                                                      |
|       41 |  0.24381700 | select SQL_NO_CACHE COUNT(*) from tours where aFCK = -214 and htlCoK = 213               |
|       42 |  0.03009800 | select SQL_NO_CACHE * from tours where aFCK = -214 and htlCoK = 213                      |
|       43 |  0.02215800 | select SQL_NO_CACHE SQL_CALC_FOUND_ROWS * from tours where aFCK = -214 and htlCoK = 213  |
|       44 |  0.00010600 | select found_rows()                                                                      |
+----------+-------------+------------------------------------------------------------------------------------------+
19 rows in set (0.00 sec)
Код:
mysql> show profile FOR QUERY 41;
+--------------------+----------+
| Status             | Duration |
+--------------------+----------+
| starting           | 0.000074 | 
| Opening tables     | 0.000015 |
| System lock        | 0.000004 |
| Table lock         | 0.000007 |
| init               | 0.000025 |
| optimizing         | 0.000013 |
| statistics         | 0.000541 |
| preparing          | 0.000020 |
| executing          | 0.000005 |
| Sending data       | 0.242889 |
| end                | 0.000009 |
| query end          | 0.000003 |
| freeing items      | 0.000204 |
| logging slow query | 0.000004 |
| cleaning up        | 0.000004 |
+--------------------+----------+
15 rows in set (0.00 sec)

mysql> show profile FOR QUERY 42;
+--------------------+----------+
| Status             | Duration |
+--------------------+----------+
| starting           | 0.000070 |
| Opening tables     | 0.000015 |
| System lock        | 0.000003 |
| Table lock         | 0.000007 |
| init               | 0.000039 |
| optimizing         | 0.000013 |
| statistics         | 0.000104 |
| preparing          | 0.000016 |
| executing          | 0.000003 |
| Sending data       | 0.029443 |
| end                | 0.000010 |
| query end          | 0.000002 |
| freeing items      | 0.000367 |
| logging slow query | 0.000003 |
| cleaning up        | 0.000003 |
+--------------------+----------+
15 rows in set (0.00 sec)

mysql> show profile FOR QUERY 43;
+--------------------+----------+
| Status             | Duration |
+--------------------+----------+
| starting           | 0.000072 | 
| Opening tables     | 0.000014 | 
| System lock        | 0.000004 | 
| Table lock         | 0.000006 | 
| init               | 0.000039 | 
| optimizing         | 0.000012 | 
| statistics         | 0.000104 | 
| preparing          | 0.000015 | 
| executing          | 0.000003 | 
| Sending data       | 0.021809 | 
| end                | 0.000012 | 
| query end          | 0.000003 | 
| freeing items      | 0.000060 | 
| logging slow query | 0.000002 | 
| cleaning up        | 0.000003 | 
+--------------------+----------+ 
15 rows in set (0.04 sec)
 

musicant

Новичок
Автор оригинала: Вурдалак
Заранее же узнать какой LIMIT подставить в запрос с SQL_CALC_FOUND_ROWS узнать нельзя.
Может я чего-то не понял, но почему нельзя?

PHP:
///функция для постраничного вывода (оригинал здесь -  php-developer.ru/category/mysql/ )
function paging ($sql, $currentPage, $onPage=20) {
$result = mysql_query('SELECT SQL_CALC_FOUND_ROWS' . $sql);
$result = mysql_fetch_assoc(mysql_query('SELECT FOUND_ROWS()'));
$totalPages = intval(($result['FOUND_ROWS()'] - 1) / $onPage) + 1;
$currentPage = empty($currentPage) || $currentPage < 0 ? 1 : intval($currentPage);
if ($currentPage > $totalPages) $currentPage = $totalPages;
$start = $currentPage * $onPage - $onPage;
$result = mysql_query('SELECT ' . $sql . 'ORDER BY Price.id DESC  LIMIT '.$start.', '.$onPage);
return $result;
}
 

dimagolov

Новичок
musicant, ты не читал или не понял что писали в теме и на что давали ссылки? тебе же сказали, что SQL_CALC_FOUND_ROWS не оптимизирован по ключам в отличии от COUNT(*), то есть сильно медленней, и поэтому использовать его нету никакого смысла?
 

musicant

Новичок
dimagolov
в данном случае я просто ответил (да и то с опиской "может я чего-то не понял"), что узнать и подставить LIMIT можно
 
Сверху