如何检查表的索引?

时间:2019-06-10 15:04:10

标签: join indexing phpmyadmin

我有一个使用phpymyadmin的网站,当我进入“状态”时,它告诉我以下内容:“不使用索引的连接数。如果该值不为0,则应仔细检查以下内容的索引:你的桌子。”该数字不为0,目前为101,但在本周末重置服务器之前,该数字已超过24K。

这是我的查询示例。不知道我的JOINS哪里出了问题,有人可以帮助我让我知道是否丢失了某些东西,或者我是否在这里多余,或者也许对如何处理索引情况做了一些解释。

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 个答案:

答案 0 :(得分:1)

很难说应该从哪里开始,但是据我所知,根据我编辑之前的问题

  • 您在php中以字符串形式输入了一个大型SQL查询。
  • 它完全没有格式。
  • 它以复杂且重复的方式编写。

所有这些都可能导致错误,难以识别并且难以修复。

  • 将sql放入自己的文件中可能是一个好主意。其他选项包括使用查询生成器工具,或将查询的复杂性作为数据库视图移动到数据库中。
  • 始终格式化所有代码,以提高可读性和可维护性。这样人们就可以为您提供帮助。
  • x <> NULLNULL,这是虚假的,因此您无需单独测试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'

请注意,这些都不能解决您实际上询问的警告消息。

但是现在您有了一个更简短,更易懂的查询,您可以希望开始思考需要有效运行哪种键和索引。