2010-03-05 3 views
0

Мне нужно оптимизировать запрос MYSQL, выполнив заказ. Независимо от того, что я делаю, mysql заканчивает работу с файловым телефоном вместо использования индекса.Порядок MYSQL отстаивает использование filesort

Вот мой стол ddl ... (Да, в этом случае столбцы DAYSTAMP и TIMESTAMP точно такие же).

CREATE TABLE DB_PROBE.TBL_PROBE_DAILY ( 
    DAYSTAMP date NOT NULL, 
    TIMESTAMP date NOT NULL, 
    SOURCE_ADDR varchar(64) NOT NULL, 
    SOURCE_PORT int(10) NOT NULL, 
    DEST_ADDR varchar(64) NOT NULL, 
    DEST_PORT int(10) NOT NULL, 
    PACKET_COUNT int(20) NOT NULL, 
    BYTES int(20) NOT NULL, 
UNIQUE KEY IDX_TBL_PROBE_DAILY_05 (DAYSTAMP,SOURCE_ADDR(16),SOURCE_PORT, 
            DEST_ADDR(16),DEST_PORT,TIMESTAMP), 
KEY IDX_TBL_PROBE_DAILY_01 (SOURCE_ADDR(16),TIMESTAMP), 
KEY IDX_TBL_PROBE_DAILY_02 (DEST_ADDR(16),TIMESTAMP), 
KEY IDX_TBL_PROBE_DAILY_03 (SOURCE_PORT,TIMESTAMP), 
KEY IDX_TBL_PROBE_DAILY_04 (DEST_PORT,TIMESTAMP), 
KEY IDX_TBL_PROBE_DAILY_06 (DAYSTAMP,TIMESTAMP,BYTES) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 

/*!50100 PARTITION BY RANGE (to_days(DAYSTAMP)) 

(PARTITION TBL_PROBE_DAILY_P20100303 VALUES LESS THAN (734200) ENGINE = InnoDB, 
PARTITION TBL_PROBE_DAILY_P20100304 VALUES LESS THAN (734201) ENGINE = InnoDB, 
PARTITION TBL_PROBE_DAILY_P20100305 VALUES LESS THAN (734202) ENGINE = InnoDB, 
PARTITION TBL_PROBE_DAILY_P20100306 VALUES LESS THAN (734203) ENGINE = InnoDB) */; 

Перегородки ежедневно, и я добавил IDX_TBL_PROBE_DAILY_06 специально для запроса я пытаюсь получить работу, которая:

select SOURCE_ADDR as 'Source_IP',  
     SOURCE_PORT as 'Source_Port', 
     DEST_ADDR as 'Destination_IP', 
     DEST_PORT as 'Destination_Port', 
     BYTES 
from TBL_PROBE_DAILY 
where DAYSTAMP >= '2010-03-04' and DAYSTAMP <= '2010-03-04' 
    and TIMESTAMP >= FROM_UNIXTIME(1267653600) and TIMESTAMP <= FROM_UNIXTIME(1267687228) 
order by bytes desc limit 20; 

объяснить план следующим образом:

+----+-------------+-----------------+---------------------------+-------+-----------------------------------------------+------------------------+---------+------+--------+-----------------------------+ | id | select_type | table | 
partitions | type | possible_keys | 
key | key_len | ref | rows | Extra | 
+----+-------------+-----------------+---------------------------+-------+-----------------------------------------------+------------------------+---------+------+--------+-----------------------------+ | 1 | SIMPLE | TBL_PROBE_DAILY | 
TBL_PROBE_DAILY_P20100304 | range | 
IDX_TBL_PROBE_DAILY_05,IDX_TBL_PROBE_DAILY_06 | IDX_TBL_PROBE_DAILY_05 | 3 | NULL | 
216920 | Using where; Using filesort | 
+----+-------------+-----------------+---------------------------+-------+-----------------------------------------------+------------------------+---------+------+--------+-----------------------------+ 

Я также пытался использовать FORCE INDEX (IDX_TBL_PROBE_DAILY_06), и в этом случае он с радостью использует IDX_06 для удовлетворения ограничений, но все же делает filesort :(

Я не могу представить, что сортировка индексов невозможна на секционированных таблицах? В этом отношении InnoDB отличается от MyISAM? Я бы подумал, что индекс InnoDBs + кэширование данных идеально подходит для сортировки индексов.

Любая помощь будет оценена по достоинству ... Я пробовал всю неделю оптимизировать этот запрос по-разному, без особого успеха.

+0

сделал все возможное, Strahd_za, пожалуйста, правильно отформатируйте свой вопрос, если вы хотите, чтобы вам помогли. – RageZ

ответ

2

Хорошо. Похоже, что обмен индексами в индексе сделал трюк.
Я действительно не знаю, почему ... может быть, у кого-то есть объяснение?

В любом случае, если я добавить индекс

create index IDX_TBL_PROBE_DAILY_07 on TBL_PROBE_DAILY(BYTES,DAYSTAMP) 

то MySQL способствует IDX07 (даже без индекса силы) и делает индекс сортировки вместо файла сортировки.

0

Я не мог прочитать определение. Здесь он отформатирован:

CREATE TABLE DB_PROBE.TBL_PROBE_DAILY ( 
    DAYSTAMP date NOT NULL, 
    TIMESTAMP date NOT NULL, 
    SOURCE_ADDR varchar(64) NOT NULL, 
    SOURCE_PORT int(10) NOT NULL, 
    DEST_ADDR varchar(64) NOT NULL, 
    DEST_PORT int(10) NOT NULL, 
    PACKET_COUNT int(20) NOT NULL, 
    BYTES int(20) NOT NULL, 
UNIQUE KEY IDX_TBL_PROBE_DAILY_05 (DAYSTAMP,SOURCE_ADDR(16),SOURCE_PORT, 
            DEST_ADDR(16),DEST_PORT,TIMESTAMP), 
KEY IDX_TBL_PROBE_DAILY_01 (SOURCE_ADDR(16),TIMESTAMP), 
KEY IDX_TBL_PROBE_DAILY_02 (DEST_ADDR(16),TIMESTAMP), 
KEY IDX_TBL_PROBE_DAILY_03 (SOURCE_PORT,TIMESTAMP), 
KEY IDX_TBL_PROBE_DAILY_04 (DEST_PORT,TIMESTAMP), 
KEY IDX_TBL_PROBE_DAILY_06 (DAYSTAMP,TIMESTAMP,BYTES) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 

/*!50100 PARTITION BY RANGE (to_days(DAYSTAMP)) 

(PARTITION TBL_PROBE_DAILY_P20100303 VALUES LESS THAN (734200) ENGINE = InnoDB, 
PARTITION TBL_PROBE_DAILY_P20100304 VALUES LESS THAN (734201) ENGINE = InnoDB, 
PARTITION TBL_PROBE_DAILY_P20100305 VALUES LESS THAN (734202) ENGINE = InnoDB, 
PARTITION TBL_PROBE_DAILY_P20100306 VALUES LESS THAN (734203) ENGINE = InnoDB) */; 

запрос:

select SOURCE_ADDR as 'Source_IP',  
     SOURCE_PORT as 'Source_Port', 
     DEST_ADDR as 'Destination_IP', 
     DEST_PORT as 'Destination_Port', 
     BYTES 
from TBL_PROBE_DAILY 
where DAYSTAMP >= '2010-03-04' and DAYSTAMP <= '2010-03-04' 
    and TIMESTAMP >= FROM_UNIXTIME(1267653600) and TIMESTAMP <= FROM_UNIXTIME(1267687228) 
order by bytes desc limit 20; 

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

Ключ в пояснении - длина ключа: это показывает, какая часть значения индекса фактически используется. Вероятно, это то же значение (3), даже когда вы вынуждаете его использовать нужный вам индекс.

+0

Thanx для подсказки. Должен ли я удалить DAYSTAMP из индекса или полностью удалить столбец TIMESTAMP (что я могу сделать в этой таблице). Думаю, я попробую оба. Просто требуется навсегда для переоценки. –

+0

Только вы знаете значение и форму ваших данных. Я не знаю, что означают ваши поля TIMESTAMP и DAYSTAMP, поэтому я не могу советовать. Для скорости вы можете просто извлечь экстракт из данных и поэкспериментировать с этим? – Martin

+0

К сожалению, не повезло. Я пробовал просто сбросить дневной столб с индекса, надеясь, что в теге where where бы сократили разделы, и один запрос диапазона по индексу поможет, но didnt. Затем я просто уронил и заново создавал таблицу (я могу генерировать новые данные достаточно быстро), без поля timestamp и сохраняя только IDX_05 и IDX_06 (единственные, которые мне нужны для этого эксперимента) ... но без столбца timestamp. По-прежнему в плане объяснения указано fileort и key_len = 3 (что я еще не совсем уверен, что это значит). –

0

Использование открытого равенства в том месте, где всегда создается файловый массив. Проще говоря, открытый < или> заставляет MySQL получать строки и заказывать их для устранения тех, которые не соответствуют вашему запросу. Если логически этот запрос можно изменить в диапазон (между меткой времени X и временной меткой Y), то MySQL может использовать эти значения bookend для получения результатов непосредственно из индекса, а затем либо filesort, если вы все еще хотите, чтобы возвращаемая сортировка была или нет, если вы хотите соответствуют значениям

0

Перекачка сделал работал, потому что

Для сортировки или группы таблицы, если сортировка или группировка выполняется на крайнем левом префиксе используемого ключа (например, ORDER BY key_part1, key_part2).Если за всеми ключевыми частями следует DESC, ключ считывается в обратном порядке. См. Раздел 8.3.1.11, «ORDER BY Optimization» и раздел 8.3.1.12 «Оптимизация GROUP BY».

+0

предоставить любую ссылку – Parvathy

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