mysql - MySQL 中非平凡 View 的性能问题

标签 mysql sql

我尝试了很长时间来创建工作 View ,如果不寻求帮助,这是不可能的。但现在, View 存在并且是用

创建的
CREATE OR REPLACE VIEW users2 AS (

SELECT DISTINCT p.username
    , p.password
    , p.firstName
    , p.lastName
    , eMail AS email
    , a.settlement AS city
    , s.name AS country
    , pl.languages
    , p.description
    , p.ID AS ID
    , p.phone1
    , p.phone2
    , CONCAT_WS(' ', a.street, a.addition) AS address
    , p.status
    , p.publicMail
    , p.advisorID
    , (SELECT DISTINCT CONCAT_WS(' ', (SELECT t.title
                                    FROM titles AS t
                                    WHERE p1.titleID = t.ID), p1.firstName, p1.lastName) AS name
        FROM persons p1, titles t
        WHERE (p1.titleID IS NULL OR p1.titleID = t.ID)
          AND p1.ID = p.advisorID) AS Betreuer
FROM addresses a, addresses_have_persons ap, countries c, persons p, states s
    , persons_language AS pl
WHERE a.ID = addressID
  AND a.Countries_ID = c.ID
  AND a.States_ID = s.ID
  AND ap.Addresses_ID = a.ID
  AND ap.Persons_ID = p.ID
  AND p.ID = pl.ID);

它应该取代名为“users”的类似表。在我的本地 MySQL 上显示“users”表最多需要两秒钟,并显示 19 条记录。要打开“users2” View 并显示相同数量的记录,但主表“persons”中有大约 150 条记录,大约需要 15 秒。

我在这里看到一个性能问题。您知道如何改进创建 View “users2”的 SELECT 吗?

我检查了子选择

SELECT DISTINCT CONCAT_WS(' ', (SELECT t.title
                                    FROM titles AS t
                                    WHERE p1.titleID = t.ID), p1.firstName, p1.lastName) AS name
    FROM persons p1, titles t
    WHERE (p1.titleID IS NULL OR p1.titleID = t.ID)
      AND p1.ID = p.advisorID

它会在一秒钟内响应。访问 View persons_language大约需要三秒钟。

提前谢谢您!

解释输出:

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   PRIMARY ap  ALL NULL    NULL    NULL    NULL    19      
1   PRIMARY p   eq_ref  PRIMARY PRIMARY 4   test_apptest.ap.Persons_ID  1   Using where
1   PRIMARY a   ALL PRIMARY NULL    NULL    NULL    4   Using where; Using join buffer (flat, BNL join) 
1   PRIMARY s   eq_ref  PRIMARY PRIMARY 4   test_apptest.a.States_ID    1   
1   PRIMARY c   eq_ref  PRIMARY PRIMARY 4   test_apptest.a.Countries_ID 1   Using index 
1   PRIMARY <derived3>  ref key0    key0    5   test_apptest.ap.Persons_ID  10
1   PRIMARY padvisor    ALL NULL    NULL    NULL    NULL    146 Using where; Using join buffer (flat, BNL join) 
1   PRIMARY t   eq_ref  PRIMARY PRIMARY 4   test_apptest.padvisor.titleID   1   Using where 
3   DERIVED lp  ALL NULL    NULL    NULL    NULL    296 Using filesort  
3   DERIVED l   eq_ref  PRIMARY PRIMARY 4   test_apptest.lp.Languages_ID    1

最佳答案

据我所知,您可以像这样重写查询:

SELECT p.username
    , p.password
    , p.firstName
    , p.lastName
    , p.eMail AS email
    , a.settlement AS city
    , s.name AS country
    , pl.languages
    , p.description
    , p.ID AS ID
    , p.phone1
    , p.phone2
    , CONCAT_WS(' ', a.street, a.addition) AS address
    , p.status
    , p.publicMail
    , p.advisorID
    , CONCAT_WS(' ', t.title, padvisor.firstName, padvisor.lastName) AS Betreuer
FROM addresses a, addresses_have_persons ap, countries c, persons p, states s
    , persons_language AS pl
LEFT JOIN persons padvisor ON padvisor.ID = p.advisorID
LEFT JOIN titles t ON t.ID = padvisor.titleID 
WHERE a.ID = p.addressID
  AND a.Countries_ID = c.ID
  AND a.States_ID = s.ID
  AND ap.Addresses_ID = a.ID
  AND ap.Persons_ID = p.ID
  AND p.ID = pl.ID;

请注意

  • 当您的架构正确规范化后,您就不需要 DISTINCT。
  • ANSI SQL 标准 '92 中引入的连接语法更具可读性。请随意将您的查询完全转换为 JOIN 语法。

对于下一步,我们需要 EXPLAIN <your_query>; 的结果以及表的创建语句,以便我们了解您的索引等。

编辑: 这是使用“现代”语法的相同查询(25 年前的东西不可能是真正现代的,但我使用的语法仍然更旧):

SELECT p.username
    , p.password
    , p.firstName
    , p.lastName
    , p.eMail AS email
    , a.settlement AS city
    , s.name AS country
    , pl.languages
    , p.description
    , p.ID AS ID
    , p.phone1
    , p.phone2
    , CONCAT_WS(' ', a.street, a.addition) AS address
    , p.status
    , p.publicMail
    , CONCAT_WS(' ', t.title, p2.firstName, p2.lastName) AS Betreuer
FROM addresses a
    INNER JOIN addresses_have_persons ap ON a.ID = ap.Addresses_ID
    INNER JOIN countries c ON a.Countries_ID = c.ID
    INNER JOIN persons p ON a.ID = p.addressID
        AND ap.Persons_ID = p.ID
    INNER JOIN states s ON a.States_ID = s.ID
    INNER JOIN persons_language pl ON p.ID = pl.ID
LEFT JOIN persons p2 ON p2.ID = p2.advisorID
LEFT JOIN titles t ON t.ID = p2.titleID;

关于mysql - MySQL 中非平凡 View 的性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45080901/

相关文章:

mysql - SQL 更新时更改计数器

asp.net - Asp 将查询放入数组并在不刷新页面的情况下通过它

mysql - 转换不在子查询中加入

php - PHP注意:未定义偏移量1

mysql - 使用带有 OUT 参数的 VB6 调用 MySQL 存储过程

mysql - 如何合并两个查询?

mysql - 总销售成本的 15%

mysql - 如何在包含来自 SQL 中另一个单元格的字符串的单元格子字符串中搜索字符串

sql - POSTGRES - 如何创建连接两个数据库的选择查询?

Java JPQL,连接表,多对多关系