【问题标题】:MySQL query taking lot of time in an AJAX requestMySQL 查询在 AJAX 请求中花费大量时间
【发布时间】:2016-08-31 06:34:12
【问题描述】:

问题

每个包含任何数据库查询的 AJAX 请求都比正常情况花费更多的时间。

我已经有一周没有更新代码库了,但是突然之间,在 AJAX 请求中完成的所有数据库查询都花费了很多时间。这里要注意的一点是,如果查询是写在一个页面中,然后页面正常加载,就像你要访问:www.example.com/mypage.php

mypage.php:

<?php

   $query = $db_handler->prepare(
      "SELECT * FROM table_x LIMIT 5"
   );
   $query->execute();
   $fetch = $query->fetchAll(PDO::FETCH_ASSOC);

?>

页面加载速度非常快,所有结果都显示出来了。

但是如果它在 AJAX 的响应文件中完成,则需要很长时间(比如 15 秒)才能加载

客户端的 AJAX 代码:

$.ajax
({
    url: 'server_files/ajaxtest.php',
    type: 'POST',
    dataType: 'JSON',
    data:
    {
        data: 'some data'
    },
    success: function(data)
    {
        if( data.success === true )
        {

        }
        else if( data.success === false )
        {

        }
    },
    error: function(e)
    {
        alert('Error');
    }
});

ajax_response.php:

<?php

   header('Content-Type: application/json');

   if( isset($_POST['data']) )
   {
       $query = $db_handler->prepare(
          "SELECT * FROM table_x LIMIT 5"
       );
       $query->execute();
       $fetch = $query->fetchAll(PDO::FETCH_ASSOC);

       echo json_encode([
           'success'  => true,
           'response' => $fetch
       ]);
    }
?>

^ 加载需要 15 秒(具有 5 个行集的查询 (LIMIT 5) 与具有 10 个行集的查询 (LIMIT 10) 所用的时间相同。

如果同一个文件只包含这个

<?php

   header('Content-Type: application/json');

   if( isset($_POST['data']) )
   {    
       echo json_encode([
           'success'  => true
       ]);
   }
?>

^ 加载需要 300-400 毫秒

显然查询会增加一点响应时间(1-3 秒),但 15 秒太多了。


我做了什么

1) 我已经联系了我的托管服务提供商,但没有太大帮助。

2) 我还安装了 mysqltuner,它显示如下:

-------- General Statistics --------------------------------------------------
[--] Skipped version check for MySQLTuner script
[OK] Currently running supported MySQL version 5.5.49-0ubuntu0.14.04.1-log
[OK] Operating on 64-bit architecture

-------- Storage Engine Statistics -------------------------------------------
[--] Status: +Archive -BDB -Federated +InnoDB -ISAM -NDBCluster
[--] Data in PERFORMANCE_SCHEMA tables: 0B (Tables: 17)
[--] Data in MyISAM tables: 27K (Tables: 13)
[--] Data in InnoDB tables: 6M (Tables: 21)
[!!] Total fragmented tables: 21

-------- Security Recommendations  -------------------------------------------
[!!] User 'rootAlbert@127.0.0.1' has no password set.
[!!] User 'rootAlbert@::1' has no password set.
[!!] User 'rootAlbert@lamp' has no password set.

-------- Performance Metrics -------------------------------------------------
[--] Up for: 11h 23m 42s (21K q [0.533 qps], 11K conn, TX: 6M, RX: 2M)
[--] Reads / Writes: 92% / 8%
[--] Total buffers: 432.0M global + 2.7M per thread (151 max threads)
[OK] Maximum possible memory usage: 837.8M (84% of installed RAM)
[OK] Slow queries: 2% (488/21K)
[OK] Highest usage of available connections: 3% (6/151)
[OK] Key buffer size / total MyISAM indexes: 16.0M/156.0K
[OK] Key buffer hit rate: 99.2% (133 cached / 1 reads)
[OK] Query cache efficiency: 61.9% (6K cached / 10K selects)
[OK] Query cache prunes per day: 0
[OK] Sorts requiring temporary tables: 0% (0 temp sorts / 113 sorts)
[!!] Temporary tables created on disk: 50% (421 on disk / 842 total)
[OK] Thread cache hit rate: 99% (6 created / 11K connections)
[OK] Table cache hit rate: 33% (75 open / 223 opened)
[OK] Open file limit used: 1% (76/6K)
[OK] Table locks acquired immediately: 100% (4K immediate / 4K locks)
[OK] InnoDB data size / buffer pool: 6.5M/128.0M

-------- Recommendations -----------------------------------------------------
General recommendations:
    Run OPTIMIZE TABLE to defragment tables for better performance
    MySQL started within last 24 hours - recommendations may be inaccurate
    When making adjustments, make tmp_table_size/max_heap_table_size equal
    Reduce your SELECT DISTINCT queries without LIMIT clauses
Variables to adjust:
    tmp_table_size (> 16M)
    max_heap_table_size (> 16M)

3) 搜索并更新了我的my.cnf 文件。 这是我的my.cnf 文件(这个文件在问题发生时看起来有点不同)

[client]
port        = 3306
socket      = /var/run/mysqld/mysqld.sock

[mysqld_safe]
socket      = /var/run/mysqld/mysqld.sock
nice        = 0

[mysqld]
local-infile=0
log=/var/log/mysql-logfile
skip_name_resolve

user        = mysql
pid-file    = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
port = 3306
basedir     = /usr
datadir = /var/lib/mysql
tmpdir      = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking

slow-query-log = 1 
slow-query-log-file = /var/log/mysql-slow.log 
long_query_time = 2 
log-queries-not-using-indexes 

key_buffer      = 16M
max_allowed_packet = 32M
thread_stack        = 192K
thread_cache_size       = 8

myisam-recover         = BACKUP

query_cache_type=1
query_cache_limit=2M
query_cache_size=256M

tmp_table_size=16M
max_heap_table_size=16M
table_cache=3084

log_error = /var/log/mysql/error.log

expire_logs_days    = 10
max_binlog_size         = 100M
big-tables

[mysqldump]
quick
quote-names
max_allowed_packet  = 16M

[mysql]

[isamchk]
key_buffer      = 16M

!includedir /etc/mysql/conf.d/

4) 优化了数据库中的所有表

5) 我还将服务器从 1GB memory and 1CPU, 2TB Transfer 升级到 2GB memory and 2CPUS, 3TB Transfer

我仍然不明白为什么会发生这种情况以及如何解决这个问题。

【问题讨论】:

  • 发布ajax_response.php文件的完整代码和你的ajax代码!!
  • 你在使用 PHP 的会话吗?阅读this
  • @Saty 发布了两个代码
  • @LuisSiquot 是的,我正在使用 PHP 的会话。
  • 听起来像会话锁定,与 mysql 本身完全无关。 stackoverflow.com/a/15693029/761202 。请将ajaxtest.php 的未修改内容放入问题中,没有它,您已经显示了很多可能无关紧要的信息。 ^ takes 300-400ms to load你如何测量这个?

标签: php jquery mysql ajax pdo


【解决方案1】:

问题出在连接字符串中。我使用我的域名 (example.com) 连接到数据库。于是我把它改成了我的IP地址,问题就解决了。

感谢大家的帮助。

【讨论】:

  • 这有点疯狂:做一次 DNS 查询会被罚 15 秒?
  • 硬编码 IP 永远都不好,找出你的 DNS 查找速度如此缓慢的原因。
  • @swa66 是的!我不知道为什么。
  • 如果需要 15 秒进行简单查找,则您的服务器的 DNS 设置不正确。当您经常进行这些查找时,它应该被缓存。管理机器的人需要解决这个问题。使用我们在此处获得的信息无法确定原因,但可能是 DNS 服务器、防火墙或网络问题,或者本地守护程序未正确执行其任务。无论哪种方式,您都会遇到其他问题,因为任何会进行 DNS 查找的操作都可能会遇到同样的问题。
  • 我在 Amazon EC2 Windows 机器上也遇到过这种情况——即便如此,从 localhost127.0.0.1 的变化也能达到目的——所以这是合法的。
【解决方案2】:

我认为你必须首先弄清楚它的查询是否需要时间。 - 将相同的查询放入 phpmyadmin 并运行查询并检查时间。如果查询需要时间,则尝试删除限制并运行或使用索引。 - 如果查询不需要时间,则在获取数据时检查网络中的任何错误或问题。暂时从 ajax 中删除查询并发送静态数据。检查它需要什么时间。

希望这会有所帮助。

【讨论】:

  • 更好,但我认为您回答得太早了Remove the query from the ajax for time being and send static data 这是问题所在。我建议删除答案,直到问题中有足够的信息来写一些具体的东西。
  • @AD7six,它是我所说的选项之一。您可以采取这些步骤来确定。至少我会先采取这些步骤。在去其他大的选择之前。
  • 删除查询并发送静态数据似乎是测试的好主意
  • 好主意,但要转移所有内容需要很长时间。如果没有 AJAX,分页、滚动加载等功能也将无法工作
  • @Devang,您可以暂时检查控制台,如果它不在现场,错误不会有关系,比如 5 分钟?
【解决方案3】:

您应该检查 MySQL 允许的总最大连接数。并在执行每个查询后查看连接是否正确关闭或释放。顺序应该是连接打开 > 执行查询 > 连接关闭。这是减慢 ajax 查询的原因之一。如果连接继续打开而不关闭,它将超出 ajax 请求的连接限制。

示例:

$db=new mysqli("localhost","root","","test"); //open the connection

$db->query("[Sql commands]");// execute query
//some php

$db->close(); //close the connection

MySQL 系统变量 max_connections 确定 MySQL/MariaDB 将接受的连接数。默认值为 151 个连接,即允许 150 个普通连接加上 1 个来自 SUPER 帐户的连接。

首先要决定的是你想为 max_connections 设置什么新的最大值。增加 MySQL/MariaDB 连接数时需要考虑几个因素。系统可以支持的最大数量取决于:

  1. 可用 RAM 的数量。
  2. 每个连接占用多少 RAM(简单查询将需要更少 RAM 比劳动密集型连接)。
  3. 可接受的响应时间。
  4. 根据 MySQL 文档,大多数 Linux 系统应该是 能够毫无困难地支持 500-1000 个连接。

要查看当前最大连接数,请使用以下命令登录 MySQL/MariaDB 命令行客户端:

mysql> show variables like 'max_connections';

使用以下命令设置新的 max_connections 值:

mysql> SET GLOBAL max_connections=[desired new maximum number];

【讨论】:

  • 请在您的答案中添加一些进一步的解释,以便其他人可以从中学习。正如您在 OP 本身给出的已接受答案中看到的那样,这是一个 DNS 问题
猜你喜欢
  • 1970-01-01
  • 2018-01-08
  • 2012-09-03
  • 1970-01-01
  • 2016-03-26
  • 1970-01-01
  • 1970-01-01
  • 2022-06-22
相关资源
最近更新 更多