php大数据优化 php如何处理大数据( 四 )


SELECT * FROM orders WHERE (customer_num=104 AND order_num1001) OR order_num=1008
虽然在customer_num和order_num上建有索引,但是在上面的语句中优化器还是使用顺序存取路径扫描整个表 。因为这个语句要检索的是分离的行的 ***,所以应该改为如下语句:
SELECT * FROM orders WHERE customer_num=104 AND order_num1001
UNION
SELECT * FROM orders WHERE order_num=1008
这样就能利用索引路径处理查询 。
4.避免相关子查询
一个列的标签同时在主查询和where子句中的查询中出现,那么很可能当主查询中的列值改变之后,子查询必须重新查询一次 。查询嵌套层次越多 , 效率越低,因此应当尽量避免子查询 。如果子查询不可避免,那么要在子查询中过滤掉尽可能多的行 。
5.避免困难的正规表达式
MATCHES和LIKE关键字支持通配符匹配 , 技术上叫正规表达式 。但这种匹配特别耗费时间 。例如:SELECT * FROM customer WHERE zipcode LIKE “98_ _ _”
即使在zipcode字段上建立了索引,在这种情况下也还是采用顺序扫描的方式 。如果把语句改为SELECT * FROM customer WHERE zipcode “98000”,在执行查询时就会利用索引来查询 , 显然会大大提高速度 。
另外 , 还要避免非开始的子串 。例如语句:SELECT * FROM customer WHERE zipcode[2,3]“80”,在where子句中采用了非开始子串,因而这个语句也不会使用索引 。
6.使用临时表加速查询
把表的一个子集进行排序并创建临时表,有时能加速查询 。它有助于避免多重排序操作 , 而且在其他方面还能简化优化器的工作 。例如:
SELECT cust.name,rcvbles.balance,……other columns
FROM cust,rcvbles
WHERE cust.customer_id = rcvlbes.customer_id
AND rcvblls.balance0
AND cust.postcode“98000”
ORDER BY cust.name
如果这个查询要被执行多次而不止一次,可以把所有未付款的客户找出来放在一个临时文件中,并按客户的名字进行排序:
SELECT cust.name,rcvbles.balance , ……other columns
FROM cust,rcvbles
WHERE cust.customer_id = rcvlbes.customer_id
AND rcvblls.balance0
ORDER BY cust.name
INTO TEMP cust_with_balance
然后以下面的方式在临时表中查询:
SELECT * FROM cust_with_balance
WHERE postcode“98000”
临时表中的行要比主表中的行少,而且物理顺序就是所要求的顺序,减少了磁盘I/O , 所以查询工作量可以得到大幅减少 。
注意:临时表创建后不会反映主表的修改 。在主表中数据频繁修改的情况下,注意不要丢失数据 。
7.用排序来取代非顺序存取
非顺序磁盘存取是最慢的操作,表现在磁盘存取臂的来回移动 。SQL语句隐藏了这一情况,使得我们在写应用程序时很容易写出要求存取大量非顺序页的查询 。
有些时候,用数据库的排序能力来替代非顺序的存取能改进查询 。
实例分析
下面我们举一个制造公司的例子来说明如何进行查询优化 。制造公司数据库中包括3个表,模式如下所示:
1.part表
零件号?????零件描述????????其他列
(part_num)?(part_desc)??????(other column)
102,032???Seageat 30G disk?????……
500 , 049???Novel 10M neork card??……
……
2.vendor表
厂商号??????厂商名??????其他列
(vendor _num)?(vendor_name) (other column)
910,257?????Seageat Corp???……
523,045?????IBM Corp?????……
……
3.parven表
零件号?????厂商号?????零件数量
(part_num)?(vendor_num)?(part_amount)