0

我正在建立一个网站 geekwiz.com。测试加载它,LONG。

我是 php 新手,只是从 mysql_query 更改为 PDO。我必须进行多次查询才能在第一页上显示产品,并且该表有超过 150 万条记录。

我怎样才能让它更快?

这是我创建的代码:

#connection
$DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
$DBH->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0);

单独的文件

#fetch data
require_once('db_config.php');
$STH = $DBH->query("
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('notebook pc - other') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 3;
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Desktop PC') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 3;
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Hard Drives - External') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 3;
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Camcorders - Analog/Digital') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 3;
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Monitors - LCD Flat Panel') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 3;
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Software - PC Games') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 3;
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('third party accessories') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 3;
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE advertisercategory LIKE ('LED TV') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 3;
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Motherboards - %') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9;
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE advertisercategory LIKE ('LED TV') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9;
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Hard Drives - External') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9;
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('CPU Cooling') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9;
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('CPU Thermal Paste / Grease') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9;
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Keyboards') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9;
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Memory (USB Flash Drive)') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9;
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Memory (Desktop Memory)') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9;
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Memory (Notebook Memory)') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9;
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Mouse') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9;
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Printer - Inkjet Printers') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9;
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Projectors') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9;
SELECT name, buyurl, imageurl, price, manufacturer, manufacturerid FROM catalog WHERE MATCH advertisercategory AGAINST ('Processors - Desktops') AND special = 'YES' AND instock = 'YES' AND standardshippingcost LIKE '0' ORDER BY lastupdated DESC limit 9;

");

$STH->setFetchMode(PDO::FETCH_OBJ);

while ($row = $STH->fetch()) {
echo "<ul>";
echo "<li>" .$row->name ."</li>";
echo "<li>" .$row->buyurl ."</li>";
echo "<li>" .$row->imageurl ."</li>";
echo "<li>" .$row->price ."</li>";
echo "<li>" .$row->manufacturer ."</li>";
echo "<li>" .$row->manufacturerid ."</li>";
echo "</ul>";
}
4

3 回答 3

2

几个问题,你可能不会喜欢我要说的。

按 text/varchar 排序非常慢,而且更新将永远持续下去。您应该做的是将所有文本转换为整数。所以advertisercategory不应该有实际的文字。相反,它应该是一个固定长度INT,链接到存储实际文本的表格。special和也是如此instockstandardshippingcost看起来像一个 varchar,因为它是单引号,如果它看起来是这样,那真的不应该是这种情况。如果它是数字,它应该是数字。我不太确定您的架构,因此standardshippingcost可能需要在catalogFK 链接到的自己的表中。 lastupdated应该是INTunix时间。

你的数据应该INT是因为1)它占用更少的空间(因此排序时的内存更少)notebook pc - other和2)更新会更快(我假设你正在使用InnoDB)。

所以,当你排序时,你SELECT所有的ids (应该是一个自动增量PRIMARY)、advertisercategoryinstockstandardshippingcoststandardshippingcostlastupdated到一个 PHP 数组中。找到最有效的方式来获得您想要的东西(您会随时找到捷径)。最后,按键SELECT的具体数据PRIMARY

我会倒过来解释。这种方法会产生最高性能的原因是,如果您在没有任何其他索引的 InnoDB 表上SELECT关闭PRIMARY,那么无论您的表有多大,它都会“立即”返回。正如您所经历的那样,使用大量深奥的查询很慢。这就是您实际检索数据的方式。

PHP 在逻辑上比 MySQL 快。这就是它的用途。堆栈上有许多 Q 表明了这一点。这就是为什么要在 PHP 上进行排序的原因。另外,如果您在数据中看到某种统计或其他类型的模式,您实际上可以编写更好的算法以使您的排序运行得更快。

除了 unix 日期之外,您的其他列不应太长。 advertisercategory可能会变得有点大,但与notebook pc - other已经是19. 我在您的 Q 中看到大约 30advertisercategory秒,所以这只是INT LENGTH 2因为那是 100 个潜在值。这将在排序时节省空间和内存。

此外,在更新时使用固定长度的整数会更快,因为聚簇表将始终保持自身紧凑和碎片整理。如果你UPDATE在集群 InnoDB 中间的一行 from'Memory (USB Flash Drive)''Projectors',你只是让你的数据库对整个数据库进行碎片整理以消除你刚刚造成的差距。如果您从一个更改110固定长度的 int 列,您就没有这样做,因为两者占用相同数量的空间,不会产生间隙,不需要对集群进行碎片整理。

当您这样做时,您会对性能的大幅提升感到震惊,但是是的,这将涉及更多代码。那么你的优先级是什么,性能还是开发时间?


哎呀!忘记了unix时间的解释。您想使用它是因为您可以将它存储INT几秒钟和几DECIMAL微秒。这样做可以在 PHP 中进行最简单的操作,因为 php 在 unix 中。

于 2013-02-10T02:15:51.107 回答
1

编写一个名为saveCacheData.php执行该组 sql 查询的 php 脚本,该脚本还将数据转储到一个名为cacheData.php.

在主页上,将 sql 查询替换为require_once('cacheData.php').

现在,当 mysql 表中的数据catalog更新时,请确保您也执行file_get_contents('saveCacheData.php')(或执行某种将为您缓存数据的 cron 作业)。

顺便说一句,我确实认为您的数据库设计可能会好很多,但是将数据库数据缓存到磁盘通常也是一个好主意。

于 2013-01-12T09:16:11.073 回答
0

好吧,首先,PDO 与巨大的数据库速度优化完全无关。
为了更清楚一点,假设您在问一个类似于“如何驾驶我的福特 Escort 从纽约布鲁克林到佛罗里达州坦帕”的问题。汽车品牌在这里无关紧要。数据库驱动程序也是如此。

现在到您的数据库。
你有很多工作要做。

首先,绝对没有办法使用Mysql FULLTEXT来做分类。它应该只是一个数字索引,链接到具有类别结构的表。

所以,查询变成了这样

SELECT * FROM catalog WHERE category=1 AND special = 'YES' AND instock = 'YES' 
AND standardshippingcost=0 ORDER BY lastupdated DESC limit 3;

而且,如果索引正确,它可以非常快。比如说,如果特价商品的数量非常有限,那么无论数据库中有多少条记录,这个字段上的索引都会让它变得更快。

但是,整体数据库架构可能会有所不同。以及可以有其他优化方式。但我们对您的项目了解不多,老实说,这不是简单的问答形式的问题。

于 2013-01-12T07:22:27.947 回答