我的SQL查询时间太长,还有其他方法吗?

时间:2019-10-23 07:14:50

标签: sql mariadb

我想在我的MariaDB中存储3D矢量图像,但是我发现检索数据花费的时间太长,无法实用。

我有几张桌子:

包含x,y和z坐标以及实体ID的点表,

包含唯一ID,实体类型(文本,线,折线等)以及其他常见属性(例如颜色和线型)的实体表,

和一些包含其他值的辅助表,例如文本,文本高度,线条粗细和标志,这些文本根据字段类型(varchar,int或float)分为不同的表。

我正在通过PHP访问数据,如下所示:

if($result = mysqli_query($conn, "SELECT entityID,X,Y,Z FROM dwgpoints WHERE drawing=".$DrawingID." AND blockID=".$blockID.";"))
{
  $previous_eID=0;
  while($row = mysqli_fetch_array($result))
  {
    $eID=$row['entityID'];
    if($previous_eID!=$eID)
    {
      if($previous_eID)// confirm it's not zero
        renderEntity($image_handle,$DrawingID,$previous_eID,$etype,$colour,$ltype,$points, $transformation, $clip);
      $previous_eID=$eID;
      if($eResult=mysqli_query($conn,"SELECT colour,ltype,etype FROM entity WHERE drawing=".$ID." AND eID=".$eID.";")){
        $erow=mysqli_fetch_assoc($eResult);
        $colour=$erow['colour'];
        $ltype=$erow['ltype'];
        $etype=$erow['etype'];
        $points=[[$row['X'],$row['Y'],$row['Z']]];
      }
    }else{
      $points[]=[$row['X'],$row['Y'],$row['Z']];
    }
  }
}

此过程最多需要十分钟,但是我知道Openstreetmaps可以从相似数量的数据中渲染图块。

EXPLAIN指令的结果如下:

MariaDB [wptest_11]> EXPLAIN SELECT entityID,X,Y,Z FROM dwgpoints WHERE drawing=2 AND blockID=-1;
+------+-------------+-----------+------+---------------+--------+---------+-------------+-------+-----------------------+
| id   | select_type | table     | type | possible_keys | key    | key_len | ref         | rows  | Extra                 |
+------+-------------+-----------+------+---------------+--------+---------+-------------+-------+-----------------------+
|    1 | SIMPLE      | dwgpoints | ref  | idx_id        | idx_id | 9       | const,const | 24939 | Using index condition |
+------+-------------+-----------+------+---------------+--------+---------+-------------+-------+-----------------------+

是否可以简化数据搜索以使处理时间易于管理?我使用的是便宜的VPS,因此可能存在硬件性能问题,在这种情况下升级会有很大不同吗?还是我需要重新考虑自己的方法?

任何建议都将受到欢迎。

1 个答案:

答案 0 :(得分:0)

作为参考,我已经在Raspberry Pi3上运行了数百万条性能更好的记录。硬件会有所帮助,但我先来看一下:

  • 在适合您的应用的情况下尽量减少通话次数
  • 在WHERE子句中的字段上添加一些索引以提高性能

单次查询

调整以下查询以适合您的需求。然后查看时间。对于26k的结果,您应该不到一秒钟。

SELECT 
    a.entityID
  , a.X
  , a.Y
  , a.Z 
  , b.colour
  , b.ltype
  , b.etype 
  , b.drawing
 FROM dwgpoints   a
 LEFT JOIN entity b 
 ON     b.eID     = a.entityID 
    AND b.drawing = a.drawing
 WHERE 
     a.drawing = ".$ID." 
 AND a.blockID = ".$blockID.
 ;

索引

创建一些索引:

  1. drawing表中blockIDdwgpoints的组合。
  2. drawing表中eIDentity的组合。

重新运行以上查询,应该有所改进。

我还将考虑在表之间添加外键,这将有助于提高数据库的数据完整性。