2010-06-04 3 views
4

Моя MySQL не очень сильная, поэтому, пожалуйста, простите любые ошибки новобранец. Короткая версия:MySQL выбирает определенные столбцы медленнее, чем выберите *

ВЫБОР locId, граф, ср ОТ destAgg_geo является значительно медленнее, чем SELECT * от destAgg_geo

prtt.destAgg представляет собой таблицу, введенные на dst_ip (Primary)

mysql> describe prtt.destAgg; 
+---------+------------------+------+-----+---------+-------+ 
| Field | Type    | Null | Key | Default | Extra | 
+---------+------------------+------+-----+---------+-------+ 
| dst_ip | int(10) unsigned | NO | PRI | 0  |  | 
| total | float unsigned | YES |  | NULL |  | 
| avg  | float unsigned | YES |  | NULL |  | 
| sqtotal | float unsigned | YES |  | NULL |  | 
| sqavg | float unsigned | YES |  | NULL |  | 
| count | int(10) unsigned | YES |  | NULL |  | 
+---------+------------------+------+-----+---------+-------+ 

GeoIP. блоки представляет собой таблицу, введенные на обоих startIpNum и endIpNum (ПЕРВИЧНЫЙ)

mysql> describe geoip.blocks; 
+------------+------------------+------+-----+---------+-------+ 
| Field  | Type    | Null | Key | Default | Extra | 
+------------+------------------+------+-----+---------+-------+ 
| startIpNum | int(10) unsigned | NO | MUL | NULL |  | 
| endIpNum | int(10) unsigned | NO |  | NULL |  | 
| locId  | int(10) unsigned | NO |  | NULL |  | 
+------------+------------------+------+-----+---------+-------+ 

destAgg_geo представляет собой вид:

CREATE VIEW destAgg_geo AS SELECT * FROM destAgg JOIN geoip.blocks 
    ON destAgg.dst_ip BETWEEN geoip.blocks.startIpNum AND geoip.blocks.endIpNum; 

Вот план оптимизации для выбора *:

mysql> explain select * from destAgg_geo; 
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra           | 
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+ 
| 1 | SIMPLE  | blocks | ALL | start_end  | NULL | NULL | NULL | 3486646 |            | 
| 1 | SIMPLE  | destAgg | ALL | PRIMARY  | NULL | NULL | NULL | 101893 | Range checked for each record (index map: 0x1) | 
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+ 

Вот план оптимизации для выбора конкретных столбцов:

mysql> explain select locId,count,avg from destAgg_geo; 
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra           | 
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+ 
| 1 | SIMPLE  | destAgg | ALL | PRIMARY  | NULL | NULL | NULL | 101893 |            | 
| 1 | SIMPLE  | blocks | ALL | start_end  | NULL | NULL | NULL | 3486646 | Range checked for each record (index map: 0x1) | 
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+ 

Вот план оптимизации для каждого столбца из destAgg и просто столбец locid от geoip.blocks:

mysql> explain select dst_ip,total,avg,sqtotal,sqavg,count,locId from destAgg_geo; 
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra           | 
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+ 
| 1 | SIMPLE  | blocks | ALL | start_end  | NULL | NULL | NULL | 3486646 |            | 
| 1 | SIMPLE  | destAgg | ALL | PRIMARY  | NULL | NULL | NULL | 101893 | Range checked for each record (index map: 0x1) | 
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+ 

Удалите колонку, кроме dst_ip и проверка диапазона переворачивает блоки:

mysql> explain select dst_ip,avg,sqtotal,sqavg,count,locId from destAgg_geo; 
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra           | 
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+ 
| 1 | SIMPLE  | destAgg | ALL | PRIMARY  | NULL | NULL | NULL | 101893 |            | 
| 1 | SIMPLE  | blocks | ALL | start_end  | NULL | NULL | NULL | 3486646 | Range checked for each record (index map: 0x1) | 
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+ 

, который затем значительно медленнее. Что тут происходит?

(Да, я мог бы просто использовать результаты * запросов и процесс оттуда, но я хотел бы знать, что происходит и почему)

EDIT - РАЗЪЯСНЯЕМ на VIEW запрос:

mysql> explain SELECT * FROM destAgg JOIN geoip.blocks ON destAgg.dst_ip BETWEEN geoip.blocks.startIpNum AND geoip.blocks.endIpNum; 
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra           | 
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+ 
| 1 | SIMPLE  | blocks | ALL | start_end  | NULL | NULL | NULL | 3486646 |            | 
| 1 | SIMPLE  | destAgg | ALL | PRIMARY  | NULL | NULL | NULL | 101893 | Range checked for each record (index map: 0x1) | 
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+ 
+0

Как определяется destAgg_geo? –

+0

Это вид: CREATE VIEW destAgg_geo AS SELECT * FROM destAgg JOIN geoip.blocks ON destAgg.dst_ip BETWEEN geoip.blocks.startIpNum И geoip.blocks.endIpNum; – Pat

+0

Пожалуйста, покажите результаты EXPLAIN в запросе, составляющем представление. –

ответ

1

MySQL может рассказать вам, если вы запускаете EXPLAIN PLAN для обоих запросов.

Первый запрос с столбцами не включает в себя никаких ключевых столбцов, поэтому я предполагаю, что он должен сделать ТАБЛИЦУ СКАНИРОВАНИЯ.

Второй запрос с «SELECT *» включает в себя первичный ключ, поэтому он может использовать индекс.

+0

EXPLAIN PLAN дает мне ошибку 1064 (зарезервированное ключевое слово): mysql> PLUS EXPLAIN select * from destAgg_geo; ERROR 1064 (42000): У вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, для правильного синтаксиса для использования рядом с 'select * from destAgg_geo' в строке 1 mysql> ПЛАН EXPLAIN (выберите * from destAgg_geo); ERROR 1064 (42000): У вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, для правильного синтаксиса для использования рядом с '(выберите * из destAgg_geo)' в строке 1 – Pat

+1

EXPLAIN PLAN - синтаксис Oracle. MySQL просто использует EXPLAIN, за которым следует запрос. –

+0

Спасибо, Билл. – duffymo

0

Я бы постарался поставить компидитный указатель на locId, count, avg и посмотреть, не ускорит ли это скорость.

1

Фильтр диапазона применяется последним, поэтому проблема заключается в том, что оптимизатор запросов выбирает сначала присоединиться к более крупной таблице в одном случае, а меньшую таблицу сначала в другую. Возможно, кто-то с большим знанием оптимизатора может рассказать нам, почему он соединяет таблицы в другом порядке для каждого.

Я думаю, что настоящая цель здесь - попытаться заставить JOIN использовать индекс, поэтому порядок соединения не будет иметь большого значения.

+0

Любые советы о том, как это сделать? – Pat

Смежные вопросы