Задавайте вопросы, мы ответим
Вы не зашли.
Доброго времени суток!
Поделитесь соображениями по сабжу плиз .
Есть таблица, содержащая, допустим, средние значения температуры за сутки.
Отредактированно deadka (11.04.2011 13:15:02)
Неактивен
deadka написал:
Возникает вопрос - почему не использует ключ, и можно ли его заставить?
Неактивен
vasya написал:
http://sqlinfo.ru/forum/viewtopic.php?pid=23966#p23966
Спасибо. То есть я инструкцией (t1.t = t2.t + interval 1 day) заставляю его проходить вычисления везде...
Тогда уточняющий вопрос - сию конструкцию можно вообще оптимально с join переписать?
Или только корелированным подзапросом (как ниже привёл)?, в нем нормально индекс используется.
Неактивен
deadka написал:
Тогда уточняющий вопрос - сию конструкцию можно вообще оптимально с join переписать?
Можно сделать ещё одно поле, хранящее разницу с предыдущим днем, и обойтись простейшим запросом
А через join оптимально на мой взгляд не выйдет.
deadka написал:
Или только корелированным подзапросом (как ниже привёл)?, в нем нормально индекс используется.
select max(abs(t1.d-(select d from weather t2 where t2.t = t1.t - interval 1 day ))) from weather t1;
mysql> explain select max(abs(t1.d-(select d from weather t2 where t2.t = t1.t - interval 1 day ))) from weather t1;
+----+--------------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | PRIMARY | t1 | ALL | NULL | NULL | NULL | NULL | 10 | |
| 2 | DEPENDENT SUBQUERY | t2 | ref | t | t | 4 | func | 2 | Using where |
+----+--------------------+-------+------+---------------+------+---------+------+------+-------------+
2 rows in set (0.00 sec)
Что-то не соображу, почему в зависимом запросе показывает rows = 2?
Неактивен
deadka написал:
set @i=NULL,@i1=NULL,@m=0;select t,d,@i1:=`d` `nextdata`,if (abs(@i1-@i)>@m,@m:=abs(@i1-@i),@m), @i:=d from `weather`;select @m;
В то же время, смущает вопрос отсутствия сортировки данных (по-хорошему ведь надо бы отсортировать перед тем, как делать проход, указанный выше).
А если сделать FORCE INDEX t, разве это не гарантирует проход в правильном направлении?
Неактивен
vasya написал:
Что-то не соображу, почему в зависимом запросе показывает rows = 2?
Честно говоря, я тоже этого не понял . Подзапрос каждый раз должен одну строку смотреть, ведь в таблице на каждом проходе лишь одно поле, годящееся под условия, а в одном случае так и вовсе ни одно не годится.
vasya написал:
deadka написал:
set @i=NULL,@i1=NULL,@m=0;select t,d,@i1:=`d` `nextdata`,if (abs(@i1-@i)>@m,@m:=abs(@i1-@i),@m), @i:=d from `weather`;select @m;
В то же время, смущает вопрос отсутствия сортировки данных (по-хорошему ведь надо бы отсортировать перед тем, как делать проход, указанный выше).А если сделать FORCE INDEX t, разве это не гарантирует проход в правильном направлении?
С такой выборкой он вообще отказывается этот ключ видеть...
Отредактированно deadka (12.04.2011 17:16:19)
Неактивен
Брр, какие у вас интересные изыскания А я — <strike>каждой бочке затычка</strike>
тоже встряну, пожалуй
Зачем в изначальном сообщении левое объединение? Оно там по смыслу не нужно
Далее — можно воспользоваться внешними знаниями, которые не доступны MySQL.
Например, отличное внешнее знание — каждая дата встречается в таблице только один
раз. Небольшое напряжение мозгов, чтобы попытаться объяснить MySQL, что это
значит на его языке (кстати, rows = 2 могло бы служить тут подсказкой, что MySQL
не понимает, что строка одна).
[silentia] root test > alter table weather drop index t, add primary key (t); Query OK, 10 rows affected (0.01 sec) Records: 10 Duplicates: 0 Warnings: 0 [silentia] root test > EXPLAIN SELECT MAX(ABS(t1.d - t2.d)) FROM weather t1, weather t2 WHERE t1.t = t2.t + INTERVAL 1 day; +----+-------------+-------+--------+---------------+---------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+--------+---------------+---------+---------+------+------+-------------+ | 1 | SIMPLE | t2 | ALL | NULL | NULL | NULL | NULL | 10 | | | 1 | SIMPLE | t1 | eq_ref | PRIMARY | PRIMARY | 4 | func | 1 | Using where | +----+-------------+-------+--------+---------------+---------+---------+------+------+-------------+ 2 rows in set (0.00 sec)
Неактивен
paulus написал:
Брр, какие у вас интересные изыскания
Ага, настолько интересные, что тебя аж передернуло .
Спасибо за подсказку насчет primary key. unique index дал тот же эффект.
Кстати говоря, после того, как я подействовал на табличку ANALYZE TABLE'ом, количество rows даже при неуникальном индексе стало равно 1, type как был ref так и остался.
mysql> explain select max(abs(t1.d-(select d from t_4104 t2 where t2.t = t1.t - interval 1 day ))) from t_4104 t1; +----+--------------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+--------------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | PRIMARY | t1 | ALL | NULL | NULL | NULL | NULL | 10 | | | 2 | DEPENDENT SUBQUERY | t2 | ref | t | t | 4 | func | 2 | Using where | +----+--------------------+-------+------+---------------+------+---------+------+------+-------------+ 2 rows in set (0.00 sec) mysql> ANALYZE TABLE t_4104; +----------------+---------+----------+----------+ | Table | Op | Msg_type | Msg_text | +----------------+---------+----------+----------+ | sqlinfo.t_4104 | analyze | status | OK | +----------------+---------+----------+----------+ 1 row in set (0.01 sec) mysql> explain select max(abs(t1.d-(select d from t_4104 t2 where t2.t = t1.t - interval 1 day ))) from t_4104 t1; +----+--------------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+--------------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | PRIMARY | t1 | ALL | NULL | NULL | NULL | NULL | 10 | | | 2 | DEPENDENT SUBQUERY | t2 | ref | t | t | 4 | func | 1 | Using where | +----+--------------------+-------+------+---------------+------+---------+------+------+-------------+ 2 rows in set (0.00 sec)
Так что возвращаясь к
vasya написал:
Что-то не соображу, почему в зависимом запросе показывает rows = 2?
то видимо, статистика индексов была неактуализированная, а после analyze table исправилась. Спасибо разделу "Оптимизация простых запросов" .
Так что актуальность осталась только у подвопроса - можно ли зафорсить использование индекса, если мы выбираем не только поле t.
vasya написал:
deadka написал:
set @i=NULL,@i1=NULL,@m=0;select t,d,@i1:=`d` `nextdata`,if (abs(@i1-@i)>@m,@m:=abs(@i1-@i),@m), @i:=d from `weather`;select @m;
В то же время, смущает вопрос отсутствия сортировки данных (по-хорошему ведь надо бы отсортировать перед тем, как делать проход, указанный выше).А если сделать FORCE INDEX t, разве это не гарантирует проход в правильном направлении?
Отредактированно deadka (12.04.2011 23:42:05)
Неактивен
Честно говоря, не понял, в чем вопрос. ORDER BY тут нет, повода для индекса
не видно
Неактивен
Это я все в контексте #5 (Васино замечание) не пойму .
Но в любом случае - индекс ведь иногда используется и без сортировки и where. вот например:
paulus написал:
Честно говоря, не понял, в чем вопрос. ORDER BY тут нет, повода для индекса
не видно
Ну вот тут тоже нет order by, однако повод для индекса он успешно находит .
В то же время если выбирать не только t, но и еще что-то, то картина совсем другая.
mysql> select t,d from t_4104_rand;
+---------------------+------+
| t | d |
+---------------------+------+
| 2011-01-09 00:00:00 | 20 |
| 2011-01-07 00:00:00 | 23 |
| 2011-01-05 00:00:00 | 29 |
| 2011-01-03 00:00:00 | 34 |
| 2011-01-01 00:00:00 | 25 |
| 2011-01-02 00:00:00 | 26 |
| 2011-01-10 00:00:00 | 22 |
| 2011-01-04 00:00:00 | 30 |
| 2011-01-08 00:00:00 | 21 |
| 2011-01-06 00:00:00 | 26 |
+---------------------+------+
10 rows in set (0.00 sec)
mysql> explain select t,d from t_4104_rand;
+----+-------------+-------------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | t_4104_rand | ALL | NULL | NULL | NULL | NULL | 10 | |
+----+-------------+-------------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)
И форс индекса ничего не даст, данные идут как в таблицу записаны.
Почему так получается?
В то же время, если создать двойной индекс.
mysql> alter table t_4104_rand add index(t,d);
Query OK, 10 rows affected (0.01 sec)
Records: 10 Duplicates: 0 Warnings: 0
mysql> select t,d from t_4104_rand;
+---------------------+------+
| t | d |
+---------------------+------+
| 2011-01-01 00:00:00 | 25 |
| 2011-01-02 00:00:00 | 26 |
| 2011-01-03 00:00:00 | 34 |
| 2011-01-04 00:00:00 | 30 |
| 2011-01-05 00:00:00 | 29 |
| 2011-01-06 00:00:00 | 26 |
| 2011-01-07 00:00:00 | 23 |
| 2011-01-08 00:00:00 | 21 |
| 2011-01-09 00:00:00 | 20 |
| 2011-01-10 00:00:00 | 22 |
+---------------------+------+
10 rows in set (0.00 sec)
mysql> explain select t,d from t_4104_rand;
+----+-------------+-------------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+-------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | t_4104_rand | index | NULL | t_2 | 13 | NULL | 10 | Using index |
+----+-------------+-------------+-------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
то опять он же - без всякого order by он все успешно сортирует и без просьбы.
Так почему он отказывается выбирать данные по индексу, если выбираем t,d, а индекс есть только на t?
Отредактированно deadka (17.04.2011 22:21:21)
Неактивен
Using index — это упоминание о том, что база не будет обращаться к данным,
достаточно данных в индексе (индекс является «накрывающим» для запроса).
Оптимизация чрезвычайно полезна для табличек MyISAM, которые кэшируют
индексы в памяти (в отличие от данных), а потому можно выдать результат
сильно быстрее. Если же надо выбрать колонку, которой нет в индексе, например,
прийдется по индексу бежать за данными (и тогда может оказаться, что проще
бежать за данными не по индексу, а полным сканом таблицы).
Неактивен
Спасибо!
Неактивен