我尝试了很长时间来创建工作 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/