Оптимизируйте запрос MySQL для предотвращения “Используя где; Используя временный файл; Используя filesort”

Из MSDN, Math.Round (double a) возвращает:

Целое число, ближайшее к a. Если дробный компонент а находится посередине между двумя целыми числами, одно из которых является четным, а другое нечетным, то возвращается четное число.

... и так, 2.5, будучи на полпути между 2 и 3, округляется до четного числа (2). это называется Банковским округлением (или округлением до четного) и является широко используемым стандартом округления.

Та же статья MSDN:

Поведение этого метода соответствует стандарту IEEE 754, раздел 4. Этот вид округления иногда называют округлением до ближайшего или округлением банкира. Он сводит к минимуму ошибки округления, возникающие в результате последовательного округления значения средней точки в одном направлении.

Вы можете указать другое поведение округления, вызвав перегрузки Math.Round, которые принимают режим MidpointRounding.

6
задан Matt 7 July 2009 в 22:05
поделиться

2 ответа

SELECT  id, name, last_reply, replies
FROM    (
        SELECT  topic_id, MAX(date) AS last_reply, COUNT(*) AS replies
        FROM    wp_pod_tbl_forum
        GROUP BY
                topic_id
        ) r
JOIN    wp_pod_tbl_forum t
ON      t.topic_id = 0
        AND t.id = r.topic_id
UNION ALL
SELECT  id, name, date, 0
FROM    wp_pod_tbl_forum t
WHERE   NOT EXISTS
        (
        SELECT  NULL
        FROM    wp_pod_tbl_forum r
        WHERE   r.topic_id = t.id
        )
        AND t.topic_id = 0
ORDER BY
       date DESC
LIMIT 0, 20

Если ваша таблица MyISAM или id не является ПЕРВИЧНЫМ КЛЮЧОМ , вам необходимо создать составной ондекс на (topic_id, id) .

Если ваша таблица - InnoDB , а id - это ПЕРВИЧНЫЙ КЛЮЧ , индекс только на ] (topic_id) подойдет ( id будет неявно добавлен в индекс).

Обновление

Этот запрос, скорее всего, будет еще более эффективным, если у вас есть индексы на (topic_id, id) и (date, id) :

Подробнее о производительности см. В этой статье в моем блоге:

Этот запрос завершается через 30 мс для 100 000 строк выборки данных:

SELECT  id, name, last_reply,
        (
        SELECT  COUNT(*)
        FROM    wp_pod_tbl_forum fc
        WHERE   fc.topic_id = fl.topic_id
        ) AS replies
FROM    (
        SELECT  topic_id, date AS last_reply
        FROM    wp_pod_tbl_forum fo
        WHERE   id = (
                SELECT  id
                FROM    wp_pod_tbl_forum fp
                WHERE   fp.topic_id = fo.topic_id
                ORDER BY
                        fp.date DESC, fp.id DESC
                LIMIT 1
                )
                AND fo.topic_id <> 0
        ORDER BY
                fo.date DESC, fo.id DESC
        LIMIT 20
        ) fl
JOIN    wp_pod_tbl_forum ft
ON      ft.id = fl.topic_id
UNION ALL
SELECT  id, name, date, 0
FROM    wp_pod_tbl_forum t
WHERE   NOT EXISTS
        (
        SELECT  NULL
        FROM    wp_pod_tbl_forum r
        WHERE   r.topic_id = t.id
        )
        AND t.topic_id = 0
ORDER BY
       last_reply DESC, id DESC
LIMIT  20

Оба индекса необходимы для того, чтобы этот запрос был эффективным.

Если ваша таблица - InnoDB и id - это ПЕРВИЧНЫЙ КЛЮЧ , то вы можете опустить id из индексов выше.

7
ответ дан 16 December 2019 в 21:44
поделиться

Вы можете разбить его на набор подзапросов (как внутренние запросы). Мне нужна схема, чтобы по-настоящему играть, но если вы

SELECT t.id, t.name, MAX(COALESCE(r.date, t.date)) AS date, COUNT(r.id) AS replies  
FROM (
   SELECT (id, name, date)
   FROM wp_pod_tbl_forum
   WHERE topic_id = 0  
) as t 
LEFT OUTER JOIN
   wp_pod_tbl_forum r
WHERE
   r.topic_id = t.id
GROUP BY
    t.id
ORDER BY
    date DESC LIMIT 0,20;

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

Есть множество способов сделать это, но самое важное, что нужно сделать при настройке SQL, - это максимально уменьшить каждый набор перед выполнением операции.

1
ответ дан 16 December 2019 в 21:44
поделиться
Другие вопросы по тегам:

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