Оптимизировать запрос?

  • Автор темы Автор темы Vadimka
  • Дата начала Дата начала

Vadimka

Новичок
Оптимизировать запрос?

Возможно ли оптимизировать данный запрос?

MyISAM, индекс стоит на d8 (timestamp), 600К записей

SELECT id, count( * ) AS COUNT
FROM view
WHERE d8
BETWEEN '".date( "Y/m/d", time( ) -60 *60 *24 *60 ). "' AND '".date( "Y/m/d"). "'
GROUP BY

выполняется почти 3 секунды ((
 
> GROUP BY
а что после группировки? потеряли кусок..

Покажите структуру таблицы..
 
вот черт 1 потерял ))

SELECT id, count( * ) AS COUNT
FROM view
WHERE d8
BETWEEN '".date( "Y/m/d", time( ) -60 *60 *24 *60 ). "' AND '".date( "Y/m/d" ). "'
GROUP BY 1


id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE view index d8 id+d8 8 NULL 630688 Using where; Using index


CREATE TABLE `view` (
`id` int(11) NOT NULL DEFAULT '0',
`id_user` mediumint(9) NOT NULL DEFAULT '0',
`ip` int(4) unsigned NOT NULL DEFAULT '0',
`idalbum` smallint(6) NOT NULL DEFAULT '0',
`d8` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY `id+idalbum+ip` (`id`,`idalbum`,`ip`),
KEY `idalbum` (`idalbum`),
KEY `id_user` (`id_user`),
KEY `ip` (`ip`),
KEY `id+d8` (`id`,`d8`),
KEY `d8` (`d8`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
 
1. Сколько записей подпадает под условие "WHERE d8 > UNIX_TIMESTAMP()-(60*60*24*60 )" ?
2. в поле id неуникальные значения ?
 
Vadimka
Попробуй так
SELECT id, count(*) AS cnt
FROM view
WHERE d8 BETWEEN DATE_SUB(NOW(), INTERVAL 60 DAY) AND NOW()
GROUP BY id
 
alpine
думаеш будет разница в скорости?

explain показывается что перебирается весь индекс.
Имхо, если количество рядов, ограничиваемое условием, существенно меньше общего количества, то стоит попробовать заставить mysql использовать индекс d8 или построить составной индекс d8+id, тогда даже с Using temporary скорость может быть выше за счёт меньшего количества строк.
 
Gas
Может и не будет. По крайней мере рекомендуют в битвине приводить параметры к единому типу.

-~{}~ 24.10.07 13:41:

ко всему прочему не мешало бы увидеть
SELECT COUNT(*) FROM view;
SELECT COUNT(*) FROM view WHERE d8 BETWEEN DATE_SUB(NOW(), INTERVAL 60 DAY) AND NOW();
 
есть разница, причем существенная, порядка 2 сек

мой запрос выполняется 3 секунды, а


SELECT id, count( * ) AS cnt
FROM view
WHERE d8
BETWEEN DATE_SUB( NOW( ) , INTERVAL 60
DAY ) AND NOW( )
GROUP BY id
Показывает записи 0 - 29 (37780 всего, Запрос занял 0.9819 сек)
 
По крайней мере рекомендуют в битвине приводить параметры к единому типу.
чё-то показалось тип поля не timestamp, а int

Vadimka
ну и кинь для интереса explain нового запроса, ключ d8 стал использоваться вместо id+d8?
 
а кинь плиз explain такого запроса:
[SQL]
SELECT id, count( * ) AS cnt
FROM view USE INDEX (d8)
WHERE d8
BETWEEN DATE_SUB( NOW( ) , INTERVAL 60
DAY ) AND NOW( )
GROUP BY id
[/SQL]
 
+----+-------------+----------------------+------+---------------+------+---------+------+--------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------------------+------+---------------+------+---------+------+--------+----------------------------------------------+
| 1 | SIMPLE | view | ALL | d8 | NULL | NULL | NULL | 633550 | Using where; Using temporary; Using filesort |
+----+-------------+----------------------+------+---------------+------+---------+------+--------+----------------------------------------------+
1 row in set (0.00 sec)
 
Vadimka
понял, спасибо.

если бы под условие попадало не более 20-25% записей, имел бы смысл ключ d8+id и order by null после группировки, иначе полный скан по ключу id+d8 выгодней, так как нет Using temporary.

alpine
спасибо что напомнил
For best results when using BETWEEN with date or time values, you should use CAST() to explicitly convert the values to the desired data type. Examples: If you compare a DATETIME to two DATE values, convert the DATE values to DATETIME values.
но у меня никакой разницы на 500K записей (версии 5.0.37 и 4.1.20) независимо от формата - со строкой сравнивается ключ или с datetime. Да и explain должен разницу показывать - при преобразовании типов (between: type conversion takes place according to the rules described in Section 12.2.2, “Type Conversion in Expression Evaluation”, but applied to all the three arguments.) индексы по идее использоваться не должны. Странно.
 
Автор оригинала: Vadimka

SELECT id, count( * ) AS cnt
FROM view
WHERE d8
BETWEEN DATE_SUB( NOW( ) , INTERVAL 60
DAY ) AND NOW( )
GROUP BY id
Показывает записи 0 - 29 (37780 всего, Запрос занял 0.9819 сек)
в продолжении этой темы, хочу полученные данные вставить в таблицу..

попробовал в массиве

while(list($fid,$v60,$ial)=r($qu)){
q("UPDATE post SET dat=dat, v60='$v60' WHERE i='$fid' ");
}

получается 11 сек. на 37К записей ((
 
как вариант: вставить в промежуточную таблицу через load data, потом update multiple-table syntax (правда на таком маленьком количестве записей выигрыша может особого и не быть).
 
п.с. может структуру таблиц изменить..? даже немогу пока представить...
есть какие-то варианты?
 
варианты... ты пробовал сделать как я написал?
откуда эти данные вообще берутся? может всё на уровне базы можно сделать, вытянуть там в temp таблицу, обработать, а потом в основную внести изменения?
 
Сверху