【发布时间】:2010-10-01 21:33:07
【问题描述】:
如何提高 mysql 数据库的性能,因为我的网站托管在共享服务器中,并且他们因为“查询太多”而暂停了我的帐户 这些东西问“索引”或“缓存”或修剪我的数据库 我不知道“索引”和缓存是什么意思以及如何在 php 上执行 谢谢
【问题讨论】:
标签: php mysql database performance caching
如何提高 mysql 数据库的性能,因为我的网站托管在共享服务器中,并且他们因为“查询太多”而暂停了我的帐户 这些东西问“索引”或“缓存”或修剪我的数据库 我不知道“索引”和缓存是什么意思以及如何在 php 上执行 谢谢
【问题讨论】:
标签: php mysql database performance caching
您可能有编写不佳的查询,和/或运行太多查询的编写不佳的页面。您能否为我们提供您正在使用的、定期运行的查询的具体示例?
【讨论】:
确定 此查询用于获取最后 3 个帖子
select * from posts where visible = 1 and date > ($server_date - 86400) and dont_show_in_frontpage = 0 order by votes*1000+((1440 - ($server_date - date))/60)*2+visites*600 desc limit 3
你怎么看?
【讨论】:
您永远不应该选择 *。相反,只选择该特定呼叫所需的数据。你在这里的意图是什么?
order by votes*1000+((1440 - ($server_date - date))/60)2+visites600 desc
【讨论】:
您可以研究以下几点:
所有这些说起来容易做起来难,但这只是一个开始。
【讨论】:
在本地设置应用程序的副本,启用 mysql 查询日志,并设置 xdebug 或其他一些分析器。开始收集数据并测试您的应用程序。有很多关于如何优化事物的指南和书籍。请务必首先花时间测试和收集数据,以便优化正确的事情。
使用您收集的数据尝试减少每次页面查看的查询次数,理想情况下,您应该能够在少于 5-10 次查询中获得所需的一切。
查看日志,看看您是否要求两次相同的事情。在代码的一部分中请求记录是一个坏主意,然后在几行之后再次从数据库中请求它,除非您确定该值可能已更改。
查找嵌入在循环中的查询,并尝试重构它们,以便进行单个查询并简单地循环结果。
您提到使用的 select * 表明您可能做错了。您可能应该列出您明确需要的字段。查看这个网站或谷歌,了解很多关于为什么select * is evil 的好论据。
开始查看您的查询,然后对它们使用explain。对于经常使用的查询,请确保它们使用良好的索引而不是进行全表扫描。调整开发数据库的索引并进行测试。
【讨论】:
首先,解雇你的主机,离开共享主机,进入一个你可以完全控制并有机会进行体面调整的环境。
在您的实验室中复制该环境,最好使用与生产环境相同的硬件;这包括诸如 RAID 控制器之类的东西。
我是否提到您需要一个 RAID 控制器。是的你是。没有一个,你就无法获得不错的写入性能——它需要一个电池支持的缓存。如果您没有,则每次写入都需要物理撞击光盘,这会破坏性能。
无论如何,回到读取性能,一旦您的机器具有与实验室生产相同规格的 RAID 控制器(当然还有相同的磁盘),您可以尝试调整。
更多 RAM 通常是获得更好性能的最便宜的方法 - 确保您已将 MySQL 配置为使用它 - 这意味着调整存储引擎的特定参数。
我在这里假设你至少有 100G 的数据;如果没有,只需购买足够的内存以使您的整个数据库都适合内存,那么读取性能基本上就解决了。
其他人提到的软件更改(例如优化查询和添加索引)也很有帮助,但只有在您拥有一个开发硬件环境后,您才能有效地进行性能工作 - 即有意义地衡量应用程序的性能 - 这意味着真实硬件(不是虚拟机),与生产中使用的硬件环境一致。
哦,是的 - 还有一件事 - 甚至不要考虑在 32 位操作系统上部署数据库服务器,这是对好内存的毁灭性浪费。
【讨论】:
对数据库表进行索引以加快查询速度。如果你不知道这意味着你什么都没有。至少,您应该在每个外键和大多数在查询的 where 子句中经常使用的字段上都有索引。假设您将主键设置为开始时,主键应该自动具有索引,在不知道索引是什么的人中我会发现这不太可能。您的表格是否标准化?
顺便说一句,既然你在做数学除法(为什么我不知道),你应该谷歌整数数学。你可能不会得到正确的结果。
【讨论】:
什么是索引:
将数据库表视为图书馆 - 您拥有大量书籍(记录),每本书都有相关数据(作者姓名、出版商、出版日期、ISBN、内容)。还假设这是一个非常幼稚的图书馆,所有书籍都按 ISBN(主键)按顺序搁置。正如书籍只能有一个物理顺序一样,数据库表也只能有一个主键索引。
现在假设有人来找图书管理员(数据库程序)说:“我想知道图书馆里有多少 Nora Roberts 的书”。要回答这个问题,图书馆员必须走在过道上,看图书馆里的每一本书,这很慢。如果图书管理员收到很多这样的请求,那么值得花时间按作者姓名(姓名索引)建立卡片目录 - 然后他可以通过参考目录而不是走在书架上来更快地回答这些问题。从本质上讲,索引设置了书籍的“替代排序” - 它将它们视为按作者的字母顺序排序。
请注意,1) 设置目录需要时间,2) 目录占用了图书馆的额外空间,以及 3) 将书籍添加到图书馆的过程变得复杂 - 而不是仅仅将书籍粘贴在上面书架上的顺序,图书管理员还必须填写索引卡并将其添加到目录中。同样,在数据库字段上添加索引可以加快查询速度,但索引本身会占用存储空间并减慢插入速度。出于这个原因,您应该只根据需要创建索引 - 索引您很少搜索的字段是没有意义的。
什么是缓存:
如果图书管理员有很多人进来并一遍又一遍地问同样的问题,那么他可能值得花时间在前台写下答案。他不必检查堆栈或目录,而是简单地说,“这是我给最后一个问这个问题的人的答案”。
在您的脚本中,这可能以不同的方式应用。您可以存储数据库查询或计算的结果或呈现网页的一部分;您可以将其存储到辅助数据库表或文件或会话变量或内存服务(如 memcached)中。您可以存储预先解析的数据库查询,准备运行。 Smarty 等一些库会自动为您存储部分或全部页面。通过存储结果并重复使用它,您可以避免多次执行相同的工作。
在任何情况下,您都必须担心答案的有效期。如果图书馆进了一本新书怎么办?可以使用可能过时五分钟的答案吗?过期一天怎么办?
缓存是非常特定于应用程序的;你将不得不考虑你的数据意味着什么,它多久改变一次,计算成本有多高,需要多久得到一次结果。如果数据变化缓慢,最好每次发生变化时重新计算并存储结果;如果它经常变化但并不重要,则仅当缓存值超过某个年龄时才更新可能就足够了。
【讨论】: