2015-10-27 5 views
0

Почему STRAIGHT_JOIN потребляет больше центрального процессора, чем обычное соединение? Есть ли у вас какие-либо идеи?Почему STRAIGHT_JOIN потребляет больше процессора?

Когда я использую straight_join по одному из моих запросов, он ускоряет запрос, например, от 12 секунд до 3 секунд. Но он потребляет столько CPU? Может быть, это касается конфигурации сервера или чего-то еще?

Вы можете проверить код после этого комментария/ Тема Идентификаторы исправны, Попадая Устройства ... /
До этой линии есть некоторый код о заполнении topic_ids на временную таблицу.

Вот запрос:

CREATE PROCEDURE `DevicesByTopic`(IN platform TINYINT, IN application TINYINT, IN topicList TEXT, IN page_no MEDIUMINT UNSIGNED) 
BEGIN 

    DECLARE m_index INT DEFAULT 0; 
    DECLARE m_topic VARCHAR(255); 
    DECLARE m_topic_id BIGINT UNSIGNED DEFAULT NULL; 
    DECLARE m_session_id VARCHAR(40) CHARSET utf8 COLLATE utf8_turkish_ci; 

    -- Session Id 
    SET m_session_id = replace(uuid(), '-', '');  

    -- Temp table 
    CREATE TEMPORARY TABLE IF NOT EXISTS tmp_topics(
     topic_slug VARCHAR(100) COLLATE utf8_turkish_ci 
     ,topic_id BIGINT UNSIGNED 
     ,session_id VARCHAR(40) COLLATE utf8_turkish_ci 
     ,INDEX idx_tmp_topic_session_id (session_id) 
     ,INDEX idx_tmp_topic_id (topic_id) 
    ) CHARSET=utf8 COLLATE=utf8_turkish_ci; 

    -- Filling topics in a loop 
    loop_topics: LOOP 
     SET m_index = m_index + 1;  

     SET m_topic_id = NULL;  
     SET m_topic= SPLIT_STR(topicList,',', m_index);      

     IF m_topic = '' THEN 
      LEAVE loop_topics;  
     END IF;   

     SELECT t.topic_id INTO m_topic_id FROM topic AS t WHERE t.application = application AND (t.slug_hashed = UNHEX(MD5(m_topic)) AND t.slug = m_topic) LIMIT 1; 

     -- Fill temp table 
     IF m_topic_id IS NOT NULL AND m_topic_id > 0 THEN   
      INSERT INTO tmp_topics 
       (topic_slug, topic_id, session_id)   
      VALUES 
       (m_topic, m_topic_id, m_session_id);    
     END IF; 

    END LOOP loop_topics;  

    /* Topic Ids are OK, Getting Devices... */ 

    SELECT 
    dr.device_id, dr.platform, dr.application, dr.unique_device_id, dr.amazon_arn 
    FROM 
    device AS dr 
    INNER JOIN (
      SELECT STRAIGHT_JOIN  
      DISTINCT 
       d.device_id 
      FROM 
       device AS d 
      INNER JOIN 
       device_user AS du ON du.device_id = d.device_id    
      INNER JOIN 
       topic_device_user AS tdu ON tdu.device_user_id = du.device_user_id 
      INNER JOIN 
       tmp_topics AS tmp_t ON tmp_t.topic_id = tdu.topic_id 
      WHERE 
       ((platform IS NULL OR d.platform = platform) AND d.application = application) 
       AND d.page_no = page_no  
     AND d.status = 1 
       AND du.status = 1    
       AND tmp_t.session_id = m_session_id COLLATE utf8_turkish_ci 
) dFiltered ON dFiltered.device_id = dr.device_id 
    WHERE 
     ((platform IS NULL OR dr.platform = platform) AND dr.application = application) 
     AND dr.page_no = page_no   
     AND dr.status = 1; 

    -- Delete rows fFill temp table 
    DELETE FROM tmp_topics WHERE session_id = m_session_id; 

END; 

С STRAIGHT_JOIN этот запрос занимает около 3 секунд, но потребляет так много ресурсов процессора, как 90%, но если я удалить ключевое слово «STRAIGHT_JOIN», он занимает 12 секунд, но потребляют 12% процессор.

MySQL 5.6.19a - InnoDB

Что может быть причиной?

С уважением.

+0

Предложение 'COLLATE' в' AND tmp_t.session_id = m_session_id COLLATE utf8_turkish_ci' отключает любую возможность использования индекса на session_id; предложите использовать последовательные сопоставления. –

+0

«Петля», возможно, можно сделать без цикла - «INSERT INTO tmp_topics SELECT ... WHERE ...». Это может ускорить процесс. –

ответ

3

A STRAIGHT_JOIN Используется, когда вам необходимо переопределить оптимизатор MySQL. Вы говорите ему, чтобы игнорировать его собственный оптимизированный путь выполнения и вместо этого полагаться на чтение таблиц в том порядке, в котором они были написаны в запросе.

99% времени, которое вы не хотите использовать straight_join. Просто полагайтесь на MySQL, чтобы сделать это, и оптимизировать путь выполнения для вас. В конце концов, любая РСУБД, которая стоит соли, будет довольно приличной при оптимизации.

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

+0

Отличное обсуждение 'straight_join'. –

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