mysql - 数据库 View 性能问题与底层查询的比较

标签 mysql database performance sql-execution-plan database-view

我注意到 View 和生成该 View 的底层 Select 语句之间的性能差异。

创建 View 时,它会对所有基础表(约 700 万行)进行表扫描,但 Select 语句不会进行此类扫描。

有人可以解释为什么会有差异吗?我如何才能使 View 像 Select 语句一样执行?

这两个查询的解释计划可以在 Google 表格中找到:Link

选择语句: 更新:我已将问题范围缩小到以下 Select 语句。看来 Group By 或 Group Concat 可能导致了该问题。

SELECT
    -- IOHD_REQUEST fields
    r.ID as requestIdMultiple
    -- KEYVALUE and MULTIPLE fields
    , CAST(GROUP_CONCAT(kv6.VALUE)AS CHAR(255)) AS CLIENT_ID
    , CAST(GROUP_CONCAT(kv1.VALUE) AS CHAR(255)) AS IDENTIFIER_ID
    , CAST(GROUP_CONCAT(ri.IDENTIFIER) AS CHAR(255)) AS IDENTIFIER
    , CAST(GROUP_CONCAT(kv7.VALUE) AS CHAR(255)) AS PLATFORM_ID
    , CAST(GROUP_CONCAT(kv8.VALUE) AS CHAR(255)) AS VENDOR_ID

FROM IOHD_REQUEST r
 LEFT JOIN IOHD_REQUEST_HELPDESK rh ON r.ID = rh.REQUEST_ID
 LEFT JOIN IOHD_REQUEST_CLIENT rc ON r.ID = rc.REQUEST_ID
 LEFT JOIN IOHD_REQUEST_IDENTIFIER ri ON r.ID = ri.REQUEST_ID
 LEFT JOIN IOHD_REQUEST_PLATFORM rp ON r.ID = rp.REQUEST_ID
 LEFT JOIN IOHD_REQUEST_VENDOR rv ON r.ID = rv.REQUEST_ID
 LEFT JOIN IOHD_REF_KEYVALUE kv1 ON (ri.IDENTIFIER_ID = kv1.KEY AND kv1.TYPE = 'IDENTIFIERTYPE')
 LEFT JOIN IOHD_REF_KEYVALUE kv6 ON (rc.CLIENT_ID = kv6.KEY AND kv6.TYPE = 'CLIENT')
 LEFT JOIN IOHD_REF_KEYVALUE kv7 ON (rp.PLATFORM_ID = kv7.KEY AND kv7.TYPE = 'PLATFORM')
 LEFT JOIN IOHD_REF_KEYVALUE kv8 ON (rv.VENDOR_ID = kv8.KEY AND kv8.TYPE = 'VENDOR')
GROUP BY r.ID;

View 的解释计划中让我困惑的一行如下。计划中的所有后续行在 View 和 select 语句之间都是相同的:

id  select_type table   partitions  type    possible_keys   key key_len ref rows    filtered    Extra
1   PRIMARY <derived2>  NULL    ALL NULL    NULL    NULL    NULL    7237546 100 NULL

指数

--
-- Indexes for table `IOHD_REF_KEYVALUE`
--
ALTER TABLE `IOHD_REF_KEYVALUE`
  ADD PRIMARY KEY (`ID`),
  ADD KEY `TYPE` (`TYPE`,`KEY`);

--
-- Indexes for table `IOHD_REQUEST`
--
ALTER TABLE `IOHD_REQUEST`
  ADD PRIMARY KEY (`ID`);

--
-- Indexes for table `IOHD_REQUEST_CLIENT`
--
ALTER TABLE `IOHD_REQUEST_CLIENT`
  ADD PRIMARY KEY (`ID`),
  ADD KEY `REQUEST_ID` (`REQUEST_ID`);

--
-- Indexes for table `IOHD_REQUEST_HELPDESK`
--
ALTER TABLE `IOHD_REQUEST_HELPDESK`
  ADD PRIMARY KEY (`ID`),
  ADD KEY `REQUEST_ID` (`REQUEST_ID`);

--
-- Indexes for table `IOHD_REQUEST_IDENTIFIER`
--
ALTER TABLE `IOHD_REQUEST_IDENTIFIER`
  ADD PRIMARY KEY (`ID`),
  ADD KEY `REQUEST_ID` (`REQUEST_ID`);

--
-- Indexes for table `IOHD_REQUEST_PLATFORM`
--
ALTER TABLE `IOHD_REQUEST_PLATFORM`
  ADD PRIMARY KEY (`ID`),
  ADD KEY `REQUEST_ID` (`REQUEST_ID`);

--
-- Indexes for table `IOHD_REQUEST_VENDOR`
--
ALTER TABLE `IOHD_REQUEST_VENDOR`
  ADD PRIMARY KEY (`ID`),
  ADD KEY `REQUEST_ID` (`REQUEST_ID`);

最佳答案

哦,键值模式的问题。除了放弃设计模式之外,我们来看看改进索引。

IOHD_REF_KEYVALUE 迫切需要帮助。

正在发生“爆炸-内爆”。即 JOIN 会导致更多行; GROUP BY 将其恢复。同时建立了一个巨大的tmp表。部分治愈方法是更换

CAST(GROUP_CONCAT(kv6.VALUE)AS CHAR(255)) AS CLIENT_ID
and
LEFT JOIN IOHD_REF_KEYVALUE kv6 ON (rc.CLIENT_ID = kv6.KEY AND kv6.TYPE = 'CLIENT')

( SELECT GROUP_CONCAT(VALUE)
      FROM IOHD_REF_KEYVALUE
      WHERE KEY = rc.CLIENT_ID
        AND TYPE = 'CLIENT'
) AS CLIENT_ID

(类似情况同上。)

修复完可以修复的问题后,请回来寻求更多帮助,但一定要带上 SHOW CREATE TABLEEXPLAIN SELECT ...

关于mysql - 数据库 View 性能问题与底层查询的比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47181826/

相关文章:

php - 如何在显示数据库 php mysql 中的表时读取表名

mysql - findOne 查询的 Mongodb 问题

MySQL IO操作超时

MYSQL - 更新 SET 值

php explode vs 列

python - 如何减少Python中比较多个字符串的处理成本?

javascript - 使用 jQuery 实现个人消息系统的实时消息计数

java - 在此示例中,Customer 或 AccountInfo 是否适合作为实体组父级?

python - 打开一个 25GB 的文本文件进行处理

Mysql性能: How to store files tree in the database?