我有一个网站页面,在加载时会针对包含150,000,000行的表格触发10个不同的查询。
通常页面加载时间不到2秒 - 但如果我经常刷新,则会产生大量查询,这会使页面加载时间减慢最多10秒。
如何避免触发所有这些查询,因为它会杀死我的数据库?
我还没有缓存。该网站以下列方式运作。我有一个表都存储了所有URI。如果用户输入了URL,我会从被调用的URL中抓取URI,并检查表是否存储了URI。如果URI存储在表中,我从关系数据库中的其他表中提取相应的数据。
来自其中一个从其他表中提取信息的PHP文件的示例代码是
<?php
set_time_limit(2);
define('MODX_CORE_PATH', '/path/to/modx/core/');
define('MODX_CONFIG_KEY','config');
require_once MODX_CORE_PATH . 'model/modx/modx.class.php';
// Criteria for foreign Database
$host = 'hostname';
$username = 'user';
$password = 'password';
$dbname = 'database';
$port = 3306;
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$dbname;port=$port;charset=$charset";
$xpdo = new xPDO($dsn, $username, $password);
// Catch the URI that is called
$pageURI = $_SERVER["REQUEST_URI"];
// Get the language token saved as TV "area" in parent and remove it
if (!isset($modx)) return '';
$top = isset($top) && intval($top) ? $top : 0;
$id= isset($id) && intval($id) ? intval($id) : $modx->resource->get('id');
$topLevel= isset($topLevel) && intval($topLevel) ? intval($topLevel) : 0;
if ($id && $id != $top) {
$pid = $id;
$pids = $modx->getParentIds($id);
if (!$topLevel || count($pids) >= $topLevel) {
while ($parentIds= $modx->getParentIds($id, 1)) {
$pid = array_pop($parentIds);
if ($pid == $top) {
break;
}
$id = $pid;
$parentIds = $modx->getParentIds($id);
if ($topLevel && count($parentIds) < $topLevel) {
break;
}
}
}
}
$parentid = $modx->getObject('modResource', $id);
$area = "/".$parentid->getTVValue('area');
$URL = str_replace($area, '', $pageURI);
$lang= $parentid->getTVValue('lang');
// Issue queries against the foreign database:
$output = '';
$sql = "SELECT epf_application_detail.description FROM epf_application_detail INNER JOIN app_uri ON epf_application_detail.application_id=app_uri.application_id WHERE app_uri.uri = '$URL' AND epf_application_detail.language_code = '$lang'";
foreach ($xpdo->query($sql) as $row) {
$output .= nl2br($row['description']);
}
return $output;
答案 0 :(得分:1)
在不知道您使用的语言的情况下,这里有一些伪代码可以帮助您入门。
您可以创建一个名为“cache”的单独表,而不是每次加载页面时触发大型查询。您可以运行查询,然后将查询中的数据存储在该缓存表中。然后当你的页面加载时,你可以查询缓存表,它会小得多,并且当你刷新页面时不会让事情陷入困境。
伪代码(可以使用cronjob等间隔完成,以保持缓存新鲜。):
运行十个大型查询
对于每个查询,将结果添加到cache
,如下所示:
query_id | query_data
----------------------------------------------------
1 | {whatever your query data looks like}
然后,当您的网页加载时,让每个查询从cache
值得注意的是,使用缓存表时,您需要经常刷新它。 (无论是经常获得更多数据,还是按照设定的间隔,例如每5分钟或更长时间。)
答案 1 :(得分:0)
您应该进行一些服务器端缓存和优化。
如果我是你,我会为你的数据库安装Memcached。
我还会考虑像Varnish这样的静态缓存,这会将每个页面缓存为静态HTML,使用varnish第2(和第3,第4,......)请求不必由PHP和MySQL处理,当你第二次加载它时(在缓存生命周期内),它会使加载速度加快很多。
最后,您可以通过安装APC(或其他操作码缓存)来帮助PHP方更好地处理数据。