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

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 секунды ((
 

JIEXA

Новичок
> GROUP BY
а что после группировки? потеряли кусок..

Покажите структуру таблицы..
 

Vadimka

Новичок
вот черт 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;
 

Gas

может по одной?
1. Сколько записей подпадает под условие "WHERE d8 > UNIX_TIMESTAMP()-(60*60*24*60 )" ?
2. в поле id неуникальные значения ?
 

alpine

Новичок
Vadimka
Попробуй так
SELECT id, count(*) AS cnt
FROM view
WHERE d8 BETWEEN DATE_SUB(NOW(), INTERVAL 60 DAY) AND NOW()
GROUP BY id
 

Gas

может по одной?
alpine
думаеш будет разница в скорости?

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

alpine

Новичок
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();
 

Vadimka

Новичок
есть разница, причем существенная, порядка 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 сек)
 

Gas

может по одной?
По крайней мере рекомендуют в битвине приводить параметры к единому типу.
чё-то показалось тип поля не timestamp, а int

Vadimka
ну и кинь для интереса explain нового запроса, ключ d8 стал использоваться вместо id+d8?
 

Gas

может по одной?
а кинь плиз 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]
 

Vadimka

Новичок
+----+-------------+----------------------+------+---------------+------+---------+------+--------+----------------------------------------------+
| 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)
 

Gas

может по одной?
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

Новичок
Автор оригинала: 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К записей ((
 

Gas

может по одной?
как вариант: вставить в промежуточную таблицу через load data, потом update multiple-table syntax (правда на таком маленьком количестве записей выигрыша может особого и не быть).
 

Vadimka

Новичок
п.с. может структуру таблиц изменить..? даже немогу пока представить...
есть какие-то варианты?
 

Gas

может по одной?
варианты... ты пробовал сделать как я написал?
откуда эти данные вообще берутся? может всё на уровне базы можно сделать, вытянуть там в temp таблицу, обработать, а потом в основную внести изменения?
 
Сверху