我对如何优化SQL查询感到有些困惑。我有一个中等复杂的查询,有一些连接每秒运行一百到一千次(SSD上有两个表,RAM中有一个表,有4个JOIN)
如何最大限度地减少执行开销?有没有办法预编译查询,以便MySQL不需要每次都分析,优化和编译查询?
我知道我可以使用预准备语句来预编译在同一会话中多次执行的查询。但是,如果您有多个会话且每个会话只有一个查询,该怎么办?准备好的语句是否在不同的会话中缓存?我不这么认为。
然后我认为存储过程是最好的方法,因为它们被称为预编译。现在我读到这个假设是完全错误的,事实上它们不预编译。
是否可以在MySQL中共享客户端会话,例如在以下会话继承的第一个会话中使用预准备语句?
最后的想法是编写一个多线程套接字服务器,就像MySQL客户端代理一样。但这对我来说似乎有点夸张。 ; - )
我使用PHP作为Apache2模块。有没有机会"存储"共享内存中的MySQL会话,以便以下HTTP请求可以使用现有的MySQL会话而不是启动新的会话?这样我可以在不同的HTTP请求中使用预准备语句吗?
答案 0 :(得分:2)
问: 有没有办法重新使用" MySQL连接,以便后续请求可以使用现有连接?
A: 是。您可以使用连接池实施。这是一种熟悉的Java模式,有几种可用的实现方式。
对于PHP中的连接池实现,您可以使用PHP扩展 mysqldnd-ms
。
参考:http://php.net/manual/en/mysqlnd-ms.pooling.php
注意:我没有使用此PHP扩展程序的个人经验。
您提出的其他一些问题......
问:如何最大限度地减少执行开销?有没有办法预编译一个查询,以便mysql不需要每次都分析,优化和编译查询?
答:在MySQL 5.6中,您可以使用服务器端预备语句。准备好的语句的执行计划缓存在会话中,因此重复调用同一SQL语句可以重用先前准备的执行计划。 (此功能在5.6之前的MySQL版本中不可用。)
减少"连接搅动**的数量将减少MySQL开销。连接和断开数据库服务器是服务器必须完成的工作。它足够简单,可以测试和比较性能。在一个进程中,打开一个连接,并做一些重复的工作(重复执行一个简单的语句,如SELECT NOW()
,然后断开连接。在另一个进程中,运行相同的SELECT重复执行,但每个连接和断开连接执行。
问:准备好的语句是否在不同的会话中缓存?
A:否。语句缓存在语句会话级别。
问:是否可以在mysql中共享客户端会话,例如在以下会话继承的第一个会话中使用预准备语句?
答:否。您实现这一目标的唯一方法是不断开与数据库的连接,并传递该会话的句柄到请求连接的后续客户端。我们通过实现连接池来实现这一目标。
答案 1 :(得分:0)
我想说,最好的做法之一是避免基于O(n)时间的查询和函数。为了能够在高负载数据下很好地执行,所有查询必须在O(1)额外时间内。这实际上意味着,无论您获取多少数据,查询总是需要相同的时间。 (线性方程式)
我的意思是,如果您将IDS存储在$_SESSION
var中,以后可以在需要将查询时间从O(n)减少到O(1)时使用它。
答案 2 :(得分:0)
如果您陷入阅读困境,Slaves可以允许几乎无限制的读取。
其他问题: - 批处理INSERT有很大帮助。 - InnoDB在并发访问方面更胜一筹。 - 跨国延迟可能导致延迟,可以通过存储过程(和其他技术)来缓解。 - 通常,您询问的开销不如查询优化重要。 - 由于延迟较少,SP有时会有所帮助。 - * Nix比Windows好。 - 太多'同时'联系可能适得其反。 - PHP会话不太可能有用。