Оптимизация SQL запроса. Что можно сделать?

День добрый!

Есть стандартная таблица CDR asterisk с несколькими дополнительными полями. В таблице около 250000 записей.

Запрос:
SELECT DISTINCT(dstnum) AS t2dstnum, MAX(calldate) OVER (PARTITION BY dstnum) AS t2lastcall FROM cdr WHERE route = "out"

выполняется около 13 минут.

Вывод EXPLAIN:
+------+-------------+-------+------+---------------+-------+---------+-------+--------+----------+----------------------------------------+
| id   | select_type | table | type | possible_keys | key   | key_len | ref   | rows   | filtered | Extra                                  |
+------+-------------+-------+------+---------------+-------+---------+-------+--------+----------+----------------------------------------+
|    1 | SIMPLE      | cdr   | ref  | route,r_and_d | route | 51      | const | 140379 |   100.00 | Using index condition; Using temporary |
+------+-------------+-------+------+---------------+-------+---------+-------+--------+----------+----------------------------------------+


Вывод SHOW PROFILE:
+-------------------------+------------+
| Status                  | Duration   |
+-------------------------+------------+
| Starting                | 0.000170   |
| Checking permissions    | 0.000020   |
| Opening tables          | 0.000050   |
| After opening tables    | 0.000017   |
| System lock             | 0.000015   |
| Table lock              | 0.000019   |
| Init                    | 0.000091   |
| Optimizing              | 0.000036   |
| Statistics              | 0.000214   |
| Preparing               | 0.000046   |
| Creating tmp table      | 0.000082   |
| Executing               | 0.000013   |
| Sending data            | 0.948192   |
| Converting HEAP to Aria | 0.073438   |
| Sending data            | 8.220165   |
| Removing duplicates     | 755.840777 |
| Removing tmp table      | 0.000293   |
| Removing duplicates     | 0.000036   |
| End of update loop      | 0.000011   |
| Query end               | 0.000005   |
| Commit                  | 0.000007   |
| Closing tables          | 0.000006   |
| Unlocking tables        | 0.000004   |
| Closing tables          | 0.000013   |
| Starting cleanup        | 0.000004   |
| Freeing items           | 0.000014   |
| Updating status         | 0.000037   |
| Reset for next command  | 0.000005   |
+-------------------------+------------+

Проблема понятно где, но как оптимизировать не разобрался. Прошу помощи у более опытных и продвинутых писателей SQL. Получится ли вообще оптимизировать?
  • Вопрос задан
  • 634 просмотра
Решения вопроса 1
@Vitsliputsli
нужно так:
SELECT 
        dstnum AS t2dstnum, 
        MAX(calldate) AS t2lastcall 
    FROM cdr 
    WHERE route = "out" 
    GROUP BY dstnum

аналитика здесь не нужна, только агрегатная функция с группировкой. В итоге, при прохождении таблицы мы не собираем дубликаты, а берем только нужные строки. Иначе, будет создана временная таблица со множеством ненужных дубликатов, на удаление которых у DISTINCT уйдет время. Судя по работе запроса, в PostgreSQL оптимизатор сам догадывается что нужно сделать именно так, в MySQL нужно задавать явно.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы