- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我几个月前写了这个查询。它运行良好。但是,这个查询的执行速度一天比一天慢。
除了同表执行之外,此查询还在多个表中检查账单历史记录。
这是查询-
SELECT * FROM (
SELECT *,
(SELECT username FROM users WHERE id = u_bills.UserId) AS username,
(SELECT first_name FROM users WHERE id = u_bills.UserId) AS first_name,
(SELECT last_name FROM users WHERE id = u_bills.UserId) AS last_name,
(SELECT phone FROM users WHERE id = u_bills.UserId) AS phone,
(SELECT email FROM users WHERE id = u_bills.UserId) AS email,
(SELECT CPRate FROM cpt WHERE UserId = u_bills.UserId ORDER BY AddedDate DESC LIMIT 0,1) AS cprate,
(SELECT (SELECT PopName FROM pops WHERE PopId = p.PopName) AS PopFullName FROM u_setupinfos AS p
WHERE UserId = u_bills.UserId) AS popname,
(SELECT active FROM users WHERE id = u_bills.UserId) AS active,
(SELECT SUM(PaidAmount) AS PaidAmount FROM u_billhistory
WHERE UserId = u_bills.UserId AND MONTH(AddedDate) = MONTH(PaidDate)) AS PaidAmount,
(SELECT PaidDate FROM u_billhistory
WHERE UserId = u_bills.UserId AND MONTH(AddedDate) = MONTH(PaidDate)
GROUP BY MONTH(PaidDate)) AS PaidDate,
(SELECT PaymentMedia FROM u_billhistory
WHERE UserId = u_bills.UserId AND MONTH(AddedDate) = MONTH(PaidDate)
GROUP BY MONTH(PaidDate)) AS PaymentMedia,
(SELECT TransactionId FROM u_billhistory
WHERE UserId = u_bills.UserId AND MONTH(AddedDate) = MONTH(PaidDate) GROUP BY MONTH(PaidDate)) AS TransactionId,
(SELECT GROUP_CONCAT(CONCAT(`BillHisId`,';',`PaidAmount`,';',`PaidDate`) separator '|') AS vals
FROM u_billhistory
WHERE UserId = u_bills.UserId
AND YEAR(PaidDate) = YEAR(CURDATE())) AS TotalPaids
FROM u_bills) AS m
WHERE m.username = 'abc'
请检查图像中的EXPLAIN
报告-
我想组织这个查询。我需要建议让这个查询更快,比如 3 到 5 秒而不是 1 分半钟或更多。我在这个查询中犯了什么错误?
重要提示-
最佳答案
它很慢,因为您要让它对结果中每条记录的每个字段运行一个单独的查找到另一个表中……有时不止一个。您应该使用 JOIN 而不是嵌套的 SELECT。对于某些分组结果,您可以加入一个 SELECT
语句,该语句执行它自己的 GROUP BY。
此外,单独列上的单独索引不要帮助!!
将索引想象成电话簿。一个简单的电话簿对姓氏和名字使用聚集索引。然后它还会列出每件商品的地址和电话号码。这就是聚簇索引:只是数据存储的顺序。
附加索引就像补充。 “电话号码”的非聚集索引就像书末的补充,按顺序列出电话号码,然后显示姓氏和名字(但不显示地址)。 “地址”上的索引会做同样的事情:一个单独的补充,按顺序列出地址,然后给你名字。
有了这些索引补充,如果你有电话号码想知道地址,你必须先在补充中查找电话号码才能找到姓名,然后在主簿中查找姓名才能得到地址。在此示例中,电话补充确实有帮助,因为它比电话簿的完整扫描更好。
但是,这里需要注意的重要一点是地址补充_does not有助于此搜索,即使地址是您想要查找的确切字段。它可能对其他搜索有用,但在这种情况下没有帮助。此外,请记住,您的图书的每次更新不仅需要更新图书,还需要更新所有的增刊。不仅仅是存储空间,还有更新每个索引所花费的时间。你需要考虑是否值得。如果您有一堆未使用的索引,最好不要使用它们。
回到您的具体问题,唯一真正能帮助您的索引是 u_bills.username
、user.UserId
(希望它的集群表)和 u_billhistory.UserId
和 u_billhistory.PaidDate
的单个索引。
这是重构此查询的初步尝试:
SELECT ub.*, u.username, u.first_name, u.last_name, u.phone, u.email, u.active,
m.PaidAmount, m.PaymentMedia, m.TransactionId,
y.TotalPaids, p.PopName As PopFullName, cpt2.CPRate
FROM u_bills ub
INNER JOIN users u on u.id = ub.UserId
INNER JOIN u_setupinfos usi on usi.UserId = ub.UserID
INNER JOIN pops p ON p.PopId = usi.PopName
INNER JOIN (
SELECT UserId, MIN(AddedDate) As cptDate
FROM cpt
GROUP BY UserID
) cpt1 ON cp1.UserID = ub.UserID
INNER JOIN (
SELECT UserID, AddedDate, MIN(CPRate) AS CPRate
FROM cpt
GROUP BY UserID, AddedDate
) cpt2 ON cpt2.UserID = ub.UserID AND cpt2.AddedDate = cpt1.ctpDate
INNER JOIN (
SELECT UserID, MONTH(PaidDate) PaidMonth, SUM(PaidAmount) AS PaidAmount,
PaymentMedia, TransactionId --these two fields need an aggregate function of some type!
FROM u_billhistory
GROUP BY UserId, MONTH(PaidDate)
) m ON m.UserID = ub.UserId AND m.PaidMonth = MONTH(ub.AddedDate)
INNER JOIN (
SELECT UserID, YEAR(PaidDate) As PaidYear,
GROUP_CONCAT(CONCAT(`BillHisId`,';',`PaidAmount`,';',`PaidDate`) separator '|') AS TotalPaids
FROM u_billhistory
WHERE YEAR(PaidDate) = YEAR(CurDate())
GROUP BY UserId, YEAR(PaidDate)
) y ON Y.UserId = ub.UserId
WHERE username='abc'
请注意,它还不够完整,因为我们没有关于您的架构和数据的所有信息,而且似乎缺少一个 GROUP BY
和两个缺少的聚合函数. MySql 在这方面很糟糕……在您修复这些问题之前,更好的数据库不会允许您的查询运行。
关于mysql - 为什么这个查询需要这么长时间才能执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40470809/
我有一个独立的 Thread 应用程序。这是一个等待消息的监听器,当消息到达时执行一些操作,其中我必须将消息保存在数据库中。但我遇到了问题,因为如果我运行应用程序并“手动发送消息”,一切都会正常工作,
我有以下php代码: sleep(65); $query = "UPDATE database.table SET XXXXXXX = XXXXXXX - ".$YYYYYY." WHERE
我正在开发一个业余爱好应用程序。它在主布局中使用 webview。单击 webview 内的链接会使用户保持在 webview 内。启动后一切正常,但仍在应用程序内。但是,在手机休眠一段时间后,我重新
我目前运行的应用程序需要最大堆大小为 16GB。 目前我使用以下标志来处理垃圾回收。 -XX\:+UseParNewGC, -XX\:+UseConcMarkSweepGC, -XX:CMSIniti
$ uname -a Darwin Wheelie-Cyberman 10.8.0 Darwin Kernel Version 10.8.0: Tue Jun 7 16:33:36 PDT 2011
在 while 循环仍在休眠时退出它的最简单方法是什么?是否有某种函数可以在 sleep 时检测某个值是否为真? 或者我是否在循环中设置一个小 sleep 并检查如果不再睡一会儿就退出?如果可以,我该
我正在 Ubunu 的 Jetty 6 上运行 Java Web 服务器,用于基于反向 ajax 的 Web。而且我在向浏览器重新发送数据的线程滞后方面遇到了严重的问题。很多时候,一些线程开始 hib
当我运行长时间操作时,我遇到来自 IIS 的请求超时。我的 ASP.NET 应用程序正在后台处理数据,但处理的记录数量很大,因此操作需要很长时间。 但是,我认为 IIS 使 session 超时。这是
我不确定从哪里开始解决这个问题,但如果我有一个 AJAX 网络应用程序向服务器发送请求并在数据库(在我的例子中是 postgresql)上运行长查询,有没有办法停止或如果仍在运行时用户刷新页面或关闭
我是一名优秀的程序员,十分优秀!