MySQL сумасшедшая справка кросс-таблицы! - PullRequest
0 голосов
/ 19 ноября 2010

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

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

Вот запрос:

SELECT DISTINCT t1.CU_ship_name1, t1.CU_ship_name2, t1.CU_email 
FROM (
      SELECT CU_id, CU_ship_name1, CU_ship_name2, CU_email
      FROM customers 
      WHERE CU_solicit=1 
      AND CU_cdate >=".$startDate." 
      AND CU_cdate <=".$endDate."
     )AS t1
INNER JOIN orders AS t2 ON t1.CU_id = t2.O_cid 
INNER JOIN item AS t3 ON t2.O_ref = t3.I_oref 
INNER JOIN product AS t4 ON t3.I_pid = t4.P_id 
INNER JOIN (
            SELECT C_id FROM category WHERE C_store_type =1
           ) AS t5 ON t4.P_cat = t5.C_id

Таблицы 'customer', 'orders', 'item' обновляются ежемесячно десятками тысяч новых строк, а таблица 'product' получает не менее ста новых строк каждый месяц.

Единственное, что я мог подумать, это создать новую таблицу, содержащую эту информацию (которая не является идеальным решением), и добавить индекс к этим таблицам. Я боюсь индекса, поскольку эти таблицы получают такое большое количество новых данных, но я готов попробовать его (всегда можно отменить это правильно?). Однако я не верю, что индекс сам решит проблему.

ОБНОВЛЕНИЕ: сейчас я использую этот запрос и получаю более быстрые результаты, индексирование всех строк WHERE и JOIN ON не очень помогло ... Я не могу понять, почему.

Удаление подзапросов:

оказал катастрофическое влияние и на мою скорость запроса: от 3-4 секунд для запроса ниже до 151 с теми же параметрами.

SELECT DISTINCT t1.CU_ship_name1, t1.CU_ship_name2, t1.CU_email 
FROM customers AS t1 
WHERE t1.CU_solicit=1 
AND t1.CU_cdate>= 20100725000000
AND t1.CU_cdate<= 20100801000000
AND EXISTS(
    SELECT NULL FROM orders AS t2
    INNER JOIN item AS t3 ON t2.O_ref = t3.I_oref 
    INNER JOIN product AS t4 ON t3.I_pid = t4.P_id 
    INNER JOIN (
        SELECT C_id 
        FROM category 
        WHERE C_store_type = 2
    ) AS t5 ON t4.P_cat = t5.C_id
    WHERE t1.CU_id = t2.O_cid);

Неважно, я изменил их на обычные соединения и никаких подзапросов, и теперь эта вещь быстро проясняется после всего. Вот запрос сейчас:

SELECT DISTINCT t1.CU_ship_name1, t1.CU_ship_name2, t1.CU_email 
FROM customers AS t1 
JOIN orders AS t2 ON t1.CU_id = t2.O_cid 
JOIN item AS t3 ON t2.O_ref = t3.I_oref 
JOIN product AS t4 ON t3.I_pid = t4.P_id 
JOIN category AS t5 ON t4.P_cat = t5.C_id 
WHERE t1.CU_solicit =1 
AND t1.CU_cdate >=20100425000000
AND t1.CU_cdate <=20100801000000
AND t5.C_store_type =2

Ответы [ 2 ]

2 голосов
/ 19 ноября 2010

Я бы попробовал две вещи:

1) Добавить индексы для столбцов, которые вы используете в предложениях ON и WHERE

2) Удалите подзапросы, переписав их как обычные JOIN и WHEREусловия

Только после того, как вы это сделали и обнаружили, что у вас все еще есть проблема, вы должны рассмотреть другие варианты.

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

Десять тысяч новых строк в месяц - ничто.Вы ставите новый ряд каждые несколько минут.Это даже не вопрос при принятии решения, какие индексы определять.MySQL на дешевом сервере может обрабатывать сотни вставок в секунду .

1 голос
/ 19 ноября 2010

Я бы проиндексировал столбцы в ваших критериях «где», а также в ваших инструкциях «ON».Индексы немедленно решат вашу проблему сбоя и, вероятно, не значительно ухудшат ваши операции модификации.Десятки тысяч строк в месяц - это на самом деле не так много строк - если только ваша БД не установлена ​​на слабой машине.

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

...