Как я могу проверить индексы моих таблиц? - PullRequest
0 голосов
/ 10 июня 2019

У меня есть веб-сайт, использующий phpymyadmin, и когда я захожу в «status», он говорит мне следующее: «Число объединений, которые не используют индексы. Если это значение не равно 0, вам следует тщательно проверить индексы ваши столы. " Число не 0, это 101 прямо сейчас, но оно было выше 24 КБ, прежде чем сервер был перезагружен в эти выходные.

Это пример запроса, который у меня есть. Не знаю, где я ошибаюсь в своих СОЕДИНЕНИЯХ, может ли кто-нибудь помочь мне сообщить мне, если я что-то упустил, или я здесь лишний, или, может быть, небольшое объяснение о том, как работать с моей ситуацией индекса.

SELECT pe_projects . *
     , pe_project_status.status_t
     , pe_project_status.orderby
     , pe_pocs.first_name AS  'poc_first_name'
     , pe_pocs.last_name 'poc_last_name'
     , pe_clients.id AS  'client_id'
     , pe_clients.short_name
     , pe_employees.first_name AS  'pe_first_name'
     , pe_employees.last_name AS  'pe_last_name'
     , (SELECT COUNT(pe_instrument_tracking.id)
          FROM pe_instrument_tracking
          WHERE pe_instrument_tracking.project_id = pe_projects.id
       ) AS total_inst
     , (SELECT (SELECT COUNT(pe_instrument_tracking.id)
                  FROM pe_instrument_tracking
                  WHERE pe_instrument_tracking.project_id = pe_projects.id
                    AND pe_instrument_tracking.ordered IS NOT NULL
                    AND pe_instrument_tracking.ordered <> '0000-00-00'
               )/COUNT(pe_instrument_tracking.id) *100
          FROM pe_instrument_tracking
          WHERE pe_instrument_tracking.project_id = pe_projects.id
       ) AS ordered_per
     , (SELECT (SELECT COUNT(pe_instrument_tracking.id)
                  FROM pe_instrument_tracking
                  WHERE pe_instrument_tracking.project_id = pe_projects.id
                    AND pe_instrument_tracking.received IS NOT NULL
                    AND pe_instrument_tracking.received <> '0000-00-00'
               )/COUNT(pe_instrument_tracking.id) *100
          FROM pe_instrument_tracking
          WHERE pe_instrument_tracking.project_id = pe_projects.id
       ) AS received_per
     , (SELECT (SELECT COUNT(pe_instrument_tracking.id)
                  FROM pe_instrument_tracking
                  WHERE pe_instrument_tracking.project_id = pe_projects.id
                    AND pe_instrument_tracking.installed IS NOT NULL
                    AND pe_instrument_tracking.installed <> '0000-00-00'
               )/COUNT(pe_instrument_tracking.id) *100
          FROM pe_instrument_tracking
          WHERE pe_instrument_tracking.project_id = pe_projects.id
       ) AS installed_per
     , (SELECT (SELECT COUNT(pe_instrument_tracking.id)
                  FROM pe_instrument_tracking
                  WHERE pe_instrument_tracking.project_id = pe_projects.id
                    AND pe_instrument_tracking.tested IS NOT NULL
                    AND pe_instrument_tracking.tested <> '0000-00-00'
               )/COUNT(pe_instrument_tracking.id) *100
          FROM pe_instrument_tracking
          WHERE pe_instrument_tracking.project_id = pe_projects.id
       ) AS tested_per
  FROM pe_projects
  JOIN pe_project_status ON pe_projects.status_id = pe_project_status.id
  JOIN pe_pocs ON pe_projects.client_contact_id = pe_pocs.id
  JOIN pe_clients ON pe_projects.client_id = pe_clients.id
  JOIN pe_employees ON pe_projects.employee_id = pe_employees.id
  WHERE NOT pe_projects.deleted
    AND pe_projects.department='1'

1 Ответ

1 голос
/ 10 июня 2019

Сложно сказать, с чего начать, но, насколько я могу судить, на основании вопроса до моего редактирования

  • У вас был большой SQL-запрос в виде строкового литерала в php.
  • Это было полностью не отформатировано.
  • Он был написан сложным и повторяющимся образом.

Все это делает ошибки вероятными, трудными для выявления и исправлениями.

  • Поместить sql в свой собственный файл может быть хорошей идеей. Другие варианты включают использование инструментов построителя запросов или перемещение сложности запроса в вашу базу данных в виде представления БД.
  • Всегда форматируйте весь код для удобочитаемости и удобства обслуживания. Это так, чтобы люди могли помочь вам с этим.
  • x <> NULL - это NULL, что неверно, поэтому вам не нужно отдельно проверять NULL.
  • Вы можете , вероятно, использовать COUNT(*) вместо COUNT(table.id), что более читабельно, но если table.id не означает, что это выглядит, значит, возможно, это неправильно.
  • Двойные SELECT - это большой красный флаг, как с точки зрения читабельности, так и с точки зрения производительности. Вы можете избавиться от них, полагаясь на тот факт, что когда вы не используете COUNT(*), COUNT не считается NULL с.
  • Рассмотрим всегда с использованием псевдонимов для таблиц, но если вы используете одну и ту же таблицу несколько раз в запросе, то вы должны безусловно псевдоним каждый раз.
  • Всегда используйте явные типы JOIN и помните о различиях между ними.
SELECT pe_projects.*
     , pe_project_status.status_t
     , pe_project_status.orderby
     , pe_pocs.first_name AS 'poc_first_name'
     , pe_pocs.last_name AS 'poc_last_name'
     , pe_clients.id AS 'client_id'
     , pe_clients.short_name
     , pe_employees.first_name AS 'pe_first_name'
     , pe_employees.last_name AS 'pe_last_name'
     , (SELECT COUNT(*)
          FROM pe_instrument_tracking pit
          WHERE pit.project_id = pe_projects.id
       ) AS total_inst
     , (SELECT COUNT(
                 CASE WHEN pit_o.ordered <> '0000-00-00' THEN pit_o.id END
               ) / COUNT(*) * 100
          FROM pe_instrument_tracking pit_o
          WHERE pit_o.project_id = pe_projects.id
       ) AS ordered_per
     , (SELECT COUNT(
                 CASE WHEN pit_r.received <> '0000-00-00' THEN pit_r.id END
               ) / COUNT(*) * 100
          FROM pe_instrument_tracking pit_r
          WHERE pit_r.project_id = pe_projects.id
       ) AS received_per
     , (SELECT COUNT(
                 CASE WHEN pit_i.installed <> '0000-00-00' THEN pit_i.id END
               ) / COUNT(*) * 100
          FROM pe_instrument_tracking pit_i
          WHERE pit_i.project_id = pe_projects.id
       ) AS installed_per
     , (SELECT COUNT(
                 CASE WHEN pit_t.tested <> '0000-00-00' THEN pit_t.id END
               ) / COUNT(*) * 100
          FROM pe_instrument_tracking pit_t
          WHERE pit_t.project_id = pe_projects.id
       ) AS tested_per
  FROM pe_projects
  LEFT JOIN pe_project_status ON pe_projects.status_id = pe_project_status.id
  LEFT JOIN pe_pocs ON pe_projects.client_contact_id = pe_pocs.id
  LEFT JOIN pe_clients ON pe_projects.client_id = pe_clients.id
  LEFT JOIN pe_employees ON pe_projects.employee_id = pe_employees.id
  WHERE NOT pe_projects.deleted
    AND pe_projects.department = '1'

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

SELECT pe_projects.*
     , pe_project_status.status_t
     , pe_project_status.orderby
     , pe_pocs.first_name AS 'poc_first_name'
     , pe_pocs.last_name AS 'poc_last_name'
     , pe_clients.id AS 'client_id'
     , pe_clients.short_name
     , pe_employees.first_name AS 'pe_first_name'
     , pe_employees.last_name AS 'pe_last_name'
     , pit.total AS total_inst
     , pit.ordered AS ordered_per
     , pit.received AS received_per
     , pit.installed AS installed_per
     , pit.tested AS tested_per
  FROM pe_projects
  LEFT JOIN pe_project_status ON pe_projects.status_id = pe_project_status.id
  LEFT JOIN pe_pocs ON pe_projects.client_contact_id = pe_pocs.id
  LEFT JOIN pe_clients ON pe_projects.client_id = pe_clients.id
  LEFT JOIN pe_employees ON pe_projects.employee_id = pe_employees.id
  LEFT JOIN (SELECT COUNT(*) AS total
                  , 100
                      * COUNT(CASE WHEN pe_instrument_tracking.ordered <> '0000-00-00' THEN 1 END)
                      / COUNT(*) AS ordered
                  , 100
                      * COUNT(CASE WHEN pe_instrument_tracking.received <> '0000-00-00' THEN 1 END)
                      / COUNT(*) AS received
                  , 100
                      * COUNT(CASE WHEN pe_instrument_tracking.installed <> '0000-00-00' THEN 1 END)
                      / COUNT(*) AS installed
                  , 100
                      * COUNT(CASE WHEN pe_instrument_tracking.tested <> '0000-00-00' THEN 1 END)
                      / COUNT(*) AS tested
               FROM pe_instrument_tracking ON pe_instrument_tracking.project_id = pe_projects.id
            ) AS pit
  WHERE NOT pe_projects.deleted
    AND pe_projects.department = '1'

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...