如何在不建立索引的情况下提高这些PHP MySQLi查询的速度?

时间:2019-03-27 04:37:55

标签: php mysqli

首先要说的是,我不能使用INDEXING,因为我需要INSERT,DELETE和UPDATE才能使此表超快。

我有一个页面,显示在数据库表中收集的订单单位的摘要。为了填充表格,创建了一个订单编号,然后将与该订单关联的各个单位扫描到表格中,以记录与每个订单关联的单位。

在本示例中,表格具有以下列。

id,UID,订单,发起方,接收方,日期时间

单个订单的单位数量可以达到1000个,整个表格正增长到成千上万个单位。

摘要页面显示每个订单的单位数以及每个订单的第一个和最后一个单位号。我将要显示的订单数限制为最后30个订单号。

例如:

订单10有200个单位。第一个UID 1510最后一个UID 1756

订单11具有300个单位。第一个UID 1922年最后一个UID 2831

..........

..........

由于代码执行以下操作,因此当前查询的响应时间约为3秒:

  1. 按ID查找最近30个订单,然后按订单编号排序

  2. 查看数组中的每个订单号

-计算具有该订单号的数据库行的数量

-从所有行中选择第一个UID作为第一个

-从所有行中选择最后一个UID作为最后一个

  1. 显示结果

我已经确定了大部分时间是通过对每个顺序中的单位数量进行计数(约1.8秒),然后确定每个顺序中的第一个和最后一个数字(约1秒)来实现的。

我真的很想知道是否有一种方法可以在不进行INDEXING的情况下加快这些查询的速度。这是带有查询的代码。

第一个请求选择按ID选择并按订单号分组的最后30个已处理订单。这将给出最后30个唯一的订单号。

$result = mysqli_query($con, "SELECT order, ANY_VALUE(receiver) AS receiver, ANY_VALUE(originator) AS originator, ANY_VALUE(id) AS id 
FROM scandb
GROUP BY order 
ORDER BY id 
DESC LIMIT 30");

在获取最后30个订单号时,会计算单位数量以及每个订单的第一个和最后一个UID。


while($row=mysqli_fetch_array($result)){

    $count = mysqli_fetch_array(mysqli_query($con, "SELECT order, COUNT(*) as count FROM scandb WHERE order ='".$row['order']."' "));

    $firstLast = mysqli_fetch_array(mysqli_query($con, "SELECT (SELECT UID FROM scandb WHERE orderNumber ='".$row['order']."' ORDER BY UID LIMIT 1) as 'first', (SELECT UID FROM barcode WHERE order ='".$row['order']."' ORDER BY UID DESC LIMIT 1) as 'last'"));

echo "<td align= center>".$count['count']."</td>";
echo "<td align= center>".$firstLast['first']."</td>";
echo "<td align= center>".$firstLast['last']."</td>";

}

数据库中有10万行,整个查询大约需要3秒钟。大多数时间在$ count和$ firstlast查询中。我想知道是否存在一种更有效的方法,可以在不编制索引的情况下更快地获取相同的数据。任何人都有的特殊技巧将不胜感激。

1 个答案:

答案 0 :(得分:1)

谨慎设计数据库

第一个技巧似乎很明显,但是事实是大多数数据库问题都来自设计不良的表结构。 例如,我见过人们在同一数据库列中存储诸如客户信息和付款信息之类的信息。对于将要使用它的数据库系统和开发人员来说,这都不是一件好事。 创建数据库时,请始终将信息放在各个表上,使用明确的命名标准并使用主键。

知道您应该优化的地方

如果要优化特定查询,则能够深入查看查询结果非常有用。使用EXPLAIN语句,您将获得关于特定查询产生的结果的大量有用信息,如以下示例所示:

EXPLAIN SELECT * FROM ref_table,other_table WHERE ref_table.key_column=other_table.column;

不要选择不需要的内容

获取所需数据的一种非常常见的方法是使用*符号,它将从所需表中获取所有字段:

SELECT * FROM wp_posts;

相反,您绝对应该只选择所需的字段,如下例所示。假设在一个很小的网站上,每分钟只有一位访问者,那不会有什么不同。但是在Cats Who Code这样的网站上,它为数据库节省了很多工作。

SELECT title, excerpt, author FROM wp_posts;

避免循环查询

在将SQL与PHP之类的编程语言一起使用时,可能很想在循环内使用SQL查询。但是,这样做就像用查询来冲击数据库。 此示例说明了整个“循环查询”问题:

foreach ($display_order as $id => $ordinal) {
    $sql = "UPDATE categories SET display_order = $ordinal WHERE id = $id";
    mysql_query($sql);
}
Here is what you should do instead:
UPDATE categories
    SET display_order = CASE id
        WHEN 1 THEN 3
        WHEN 2 THEN 4
        WHEN 3 THEN 5
    END
WHERE id IN (1,2,3)

使用联接而不是子查询

作为程序员,子查询很容易被使用和滥用。如下所示,子查询可能非常有用:

SELECT a.id,
    (SELECT MAX(created)
    FROM posts
    WHERE author_id = a.id)
AS latest_post FROM authors a

尽管子查询很有用,但通常可以用联接来代替子查询,这无疑是执行起来更快的

SELECT a.id, MAX(p.created) AS latest_post
FROM authors a
INNER JOIN posts p
    ON (a.id = p.author_id)
GROUP BY a.id

来源:http://20bits.com/articles/10-tips-for-optimizing-mysql-queries-that-dont-suck/