最近我们的 mysql 服务器出现了很多问题,网站速度非常慢,甚至根本无法加载。该服务器是专用服务器,仅运行我们的 mysql 数据库。我一直在使用分析器 (JetProfiler) 和压力测试工具 (loadUI) 进行一些测试。
如果我使用 loadUI 连接 50 个同时连接到我们运行最近大查询的网站之一,它已经会导致网站无法加载。让我担心的事情之一是,当我查看 Jetprofile 时,它总是显示 Treads_connected 为 1.00,并且似乎当它达到 2.00 左右时我无法连接。
当我使用 loadUI 运行测试时出现了 3 个大峰值,第一个峰值有 15 个同时连接,这虽然仍然可以加载网站,但速度非常慢;第二个峰值有 40 个同时连接,这已经无法加载;第三个峰值有 100 个连接,但这也导致网站无法再加载。
另一件让我担心的事情是,JetProfiler 中显示所有使用的查询都是全表扫描,这可能是问题所在吗?我测试运行的网站运行 3 个查询,一个用于输出约 1000 行的菜单,一个用于约 560 行的添加,一个用于获取约 7000 行的帖子(见下面的屏幕截图)
我也监控了服务器的 CPU,那里似乎没有问题,即使我使用 loadui 建立大量连接,CPU 仍然保持在低水平。
我似乎无法弄清楚网站在流量很大时无法加载的主要原因是什么,如果有人有其他测试建议或可能导致问题的原因,请告诉我。
答案1
一些漂亮的图片,但是您的帖子缺少很多信息。
最大连接数是多少?数据库有多大?什么引擎?密钥缓冲区大小是多少?DBMS 有多少可用内存?
全表扫描,这可能是问题所在吗?
可能是 - 信息量不够。如果查询需要读取超过约十分之一的数据,则全表扫描将比索引查找更快。
查询,一个用于输出约 1000 行的菜单
您的网页上有 1000 个菜单?那么您的大部分问题都不在数据库中。您的应用程序从数据库获取了太多数据。如果它通过互联网发送这些信息,那么性能就会骇人听闻。如果它没有发送它所获取的所有数据,那么为什么不对 DBMS 进行过滤。
每个表都有一个主索引
也许您应该考虑将您的模式与您的查询对齐(即添加相关索引),然而您认为您遇到的最大问题是您正在从尚未使用的 DBMS 中获取数据。
另一方面,你的意思是,当你使用与屏幕截图中相同的工具分析查询时,它会告诉你正在处理数千行?在这种情况下,修复索引将产生巨大的影响。
答案2
当同时连接数增加时,速度会变慢,这可能是连接池问题。如果服务器/连接池设置为仅允许一定数量的连接(例如 5 个),那么后面的连接将排队,直到队列中有空间。此外,如果单个页面点击导致触发各种 SQL 查询,但每个查询都会打开一个全新的 MySQL 连接(而不是重新使用较早的连接),那么这可能会导致生成大量连接请求。
如何控制连接池取决于具体实现(不同的语言/库以不同的方式实现),并且对于保持打开的数据库连接数,有一个最佳点。使用 Tomcat 等系统,Tomcat 本身可以设置为在启动时打开数据库连接,并在需要时为应用程序/servlet 提供这些连接。您必须分析您的应用程序和使用情况,以了解合理的最佳点(因为保持打开不必要的连接会占用内存)。
否则,大多数用于网络内容的脚本语言(作为示例)都有数据库库,它们会在页面开始时打开一个连接,然后您只需将该引用重新用于页面的其余部分即可。值得检查这种情况是否正在发生(尽管您可能无法对代码进行大规模控制)。
我根据工作中遇到的 Tomcat Web 应用程序与专有数据库系统之间的连接池时间问题得出了此结论。这可能不相关。
答案3
另一件令我担心的事情是,JetProfiler 显示所有使用的查询都是全表扫描,这可能是问题所在吗?
哦是的!
正如我喜欢说的那样:
做任何事情(比如读取数据库行)都需要一定的时间。
做同样的事情千需要时间至少一千倍那么长。
当数据库有索引来支持正在运行的查询时,它们会工作得很好。索引允许它们立即找到所需的行,非常快多了。
对于您显示的查询,我建议在三个全部where 子句中的这些字段 - webid、actief 和 datum - 以及大概按此顺序。玩;实验当然,在你的开发/测试数据库中,使用真实数据量和不同的索引运行此查询,不是在你的生产中 - 看看什么最适合你的工作量。