0

我有一个我认为是复杂的 php mysql 查询,它从各种 drupal 表中提取数据,并允许我通过 php 以 json 格式输出结果。有时这个查询很快,有时又很慢。如果您访问 http://www.serviidb.com/content/data/view/api_access,您可以看到实际的 API 响应时间。数据库中的内容一直在增长,而且随着数据库变得越来越大,这个问题只会变得更糟。

抱歉忘记添加服务器信息:

Server: Localhost via UNIX socket
Server version: 5.5.29-0ubuntu0.12.04.1-log
Protocol version: 10

我如何调用查询的示例。

mysql_query($sqlApiAccess) or die('Error, insert query failed');

如果有人想查看我正在使用的 PHP,请询问,我会发布它。我已经编程多年,但对 PHP 很陌生,所以我可能正在做所有事情。

我感谢任何人能给我的任何帮助、指导或建议。

这是查询:

SELECT DISTINCT
   node.title AS "name",
   regions.region AS region,
   field_data_field_media_url.field_media_url_value AS url,
   media_type.media_type AS mediaType,
   repositoryType.repositoryType AS resourceType,
   plugins.plugin,
   media_resource_language.language,
   node.nid,
   resolution.resolution,
   (field_data_field_quality.field_quality_rating / 20) AS quality,
   (field_data_field_reliability.field_reliability_rating / 20)
      AS reliability,
   field_data_field_installs.field_installs_value AS installCount
FROM node
   LEFT JOIN field_data_field_region
      ON field_data_field_region.revision_id = node.vid
   LEFT JOIN regions
      ON regions.tid = field_data_field_region.field_region_tid
   LEFT JOIN field_data_field_media_url
      ON field_data_field_media_url.revision_id = node.vid
   LEFT JOIN field_data_field_required_plugin
      ON field_data_field_required_plugin.revision_id = node.vid
   LEFT JOIN field_data_field_source
      ON field_data_field_source.revision_id = node.vid
   LEFT JOIN repositoryType
      ON repositoryType.tid = field_data_field_source.field_source_tid
   LEFT JOIN plugins
      ON plugins.tid =
            field_data_field_required_plugin.field_required_plugin_tid
   LEFT JOIN field_data_field_media_type
      ON field_data_field_media_type.revision_id = node.vid
   LEFT JOIN media_type
      ON media_type.tid =
            field_data_field_media_type.field_media_type_tid
   LEFT JOIN field_data_field_language
      ON field_data_field_language.revision_id = node.vid
   LEFT JOIN media_resource_language
      ON media_resource_language.tid =
            field_data_field_language.field_language_tid
   LEFT JOIN field_data_field_resolution
      ON field_data_field_resolution.revision_id = node.vid
   LEFT JOIN resolution
      ON resolution.tid =
            field_data_field_resolution.field_resolution_tid
   LEFT JOIN field_data_field_quality
      ON field_data_field_quality.revision_id = node.vid
   LEFT JOIN field_data_field_reliability
      ON field_data_field_reliability.revision_id = node.vid
   LEFT JOIN field_data_field_installs
      ON field_data_field_installs.revision_id = node.vid
WHERE     node.status <> 0
   AND node.type = "media"
   AND (node.title LIKE '%%' OR plugins.plugin LIKE '%%')
   AND node.title LIKE '%%'
   AND plugins.plugin LIKE '%%'
   AND media_resource_language.language LIKE '%%'
   AND (regions.region = "worldwide" OR regions.region LIKE '%%')
   AND media_type.media_type = "video"

我读到如果使用“Like”,它会导致查询运行缓慢,所以我正在寻找几种方法来删除Like部分,除非实际变量中有信息。以下是我目前正在开发 where 部分的方式。

/** setups up sql variable for searches.
     *
     */
    $sqlregion        = "";
    $sqltitle         = "";


            $sqlregion        = 'and (regions.region = "worldwide" or ';
            $sqlregion        = $sqlregion . 'regions.region like ';
            $sqlregion        = $sqlregion . "'%";
            $sqlregion        = $sqlregion . $region;
            $sqlregion        = $sqlregion . "%')";

    $slqLanguage      = "and media_resource_language.language like '%" . $language . "%'";
    $sqltitleOrPlugin = "and (node.title like '%" . $titleOrPlugin . "%' or plugins.plugin like '%" . $titleOrPlugin . "%')";

    $sqlPlugin        = "and plugins.plugin like '%" . $plugin . "%'";

    $sqltitle         = "and node.title like '%" . $title . "%'";

Where 语句是这样设置的。

WHERE node.status<>0 and node.type="media" . $sqltitleOrPlugin . $sqltitle .$sqlPlugin . $slqLanguage . $sqlregion;

where 变量实际上是第三方应用程序填充以缩小数据范围的参数。就像这样 language=en®ion=us&title=the&client=test

WHERE node.status<>0 
    and node.type="media"
    and (node.title like '%%' or plugins.plugin  like '%%')
    and node.title like '%%'
    and plugins.plugin like '%%'
    and media_resource_language.language like '%%'
    and (regions.region = "worldwide" or regions.region like '%us%') 
    and media_type.media_type ="video"
4

1 回答 1

0

MySQL 完全有可能缓存您的查询结果。首先,有通用的MySQL 查询缓存。使用 InnoDB 存储引擎时,还有InnoDB 缓冲池。两个缓存都能够将 SELECT 查询及其结果存储在内存中,从而实现非常快速的响应。

但是,这些缓存通常会在其中一个受影响的表中的数据被更新时被刷新(这样做是为了确保 MySQL 不会提供过时的结果)。此外,当达到最大缓存大小时,通常会从缓存中清除不常用的结果。

您的查询连接了很多表并包含一条DISTINCT语句,因此可能会导致大量 IO;此外,MySQL 可能需要使用临时表来构建结果(这些可能会偶尔写入磁盘,从而导致更多的 IO)。因此构建第一个结果集可能需要相当长的时间,而后续请求可以从查询缓存中快速得到响应。当数据发生变化或缓冲区大小耗尽时,缓存结果会从缓存中刷新,下次调用会再次变慢。

您可以尝试调整缓冲池配置参数(例如通过增加innodb_buffer_pool_size,尽管我不是这方面的专家),以便将您的结果保留在缓存中更长的时间。

于 2013-02-28T22:27:26.990 回答