2016-11-07 4 views
0

У меня есть следующие таблицы и запроса в MySQL:ограничение на группы по столбцу

CREATE TABLE IF NOT EXISTS `events` (
    `pv_name` varchar(60) COLLATE utf8mb4_unicode_ci NOT NULL, 
    `time_stamp` bigint(20) unsigned NOT NULL, 
    `event_type` varchar(40) COLLATE utf8mb4_unicode_ci NOT NULL, 
    `data` json, 
    PRIMARY KEY (`pv_name`,`time_stamp`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=COMPRESSED; 

CREATE TEMPORARY TABLE matching_pv_names (
pv_name varchar(60) NOT NULL, 
PRIMARY KEY (pv_name) 
) ENGINE=Memory; 

SELECT events.pv_name, MAX(events.time_stamp) AS time_stamp 
FROM events 
WHERE events.time_stamp <= @time_stamp_in 
GROUP BY events.pv_name; 

Запрос, как он стоит работает эффективно с "Использование индекса для группы-по. Можно ли изменить его, чтобы ограничить набор групп pv_names, которые он группирует, для групп в таблице matching_pv_names и по-прежнему поддерживать оптимизацию «Использование индекса для групповой»? Например, следующий запрос больше не использует эту оптимизацию:

SELECT events.pv_name, MAX(events.time_stamp) AS time_stamp 
FROM events 
WHERE events.time_stamp <= @time_stamp_in 
AND events.pv_name IN (SELECT matching_pv_names.pv_name FROM matching_pv_names) 
GROUP BY events.pv_name; 

Есть ли другой способ написать его так, чтобы он это сделал?

ответ

1

Ваш первый SQL может выиграть от оптимизации GROUP BY, потому что он использует только одну таблицу, а столбец, который вы используете для GROUP BY, имеет индекс, и единственная функция агрегата, которую вы используете, - MAX(). и вы используете константу в своем предложении WHERE.

Как только вы добавите другую таблицу в запрос, тогда GROUP BY optimization не может быть применен.

+0

Я думаю, что вы правы. Я надеялся, что может быть работа вокруг, потому что я могу добавить 'WHERE events.pv_name LIKE' в запрос и сохранить оптимизацию. – Patrick

+0

Вы не должны стремиться к определенной оптимизации, а скорее стремиться к «лучшей» оптимизации. –

+0

Я считаю, что это лучшая оптимизация, как по документации, так и при тестировании в моем наборе данных. – Patrick

0

Вы задали вопрос об определенной оптимизации, но не вопрос real вопрос об эффективности?

Посмотрите, как хорошо это работает:

SELECT e.pv_name, MAX(e.time_stamp) AS time_stamp 
    FROM events AS e 
    JOIN matching_pv_names AS m USING(pv_name) 
    WHERE e.time_stamp <= @time_stamp_in 
    GROUP BY e.pv_name; 

Один из способов, чтобы сравнить эффективность двух запросов, даже когда таблицы мало,

FLUSH STATUS; 
SELECT ...; 
SHOW SESSION STATUS LIKE 'Handler%'; 

Исторически эта конструкция была оптимизирована плохо: IN (SELECT ...). (Я не знаю, работает ли он плохо для вашего запроса в вашей версии.)