不使用索引的Mysql查询
我在mysql中有一个相当大的订单表(大约120k行,并且还在增长),我在mysql慢速日志中看到一些查询花费的时间太长。 由于这个原因,我在服务器上也有一些峰值负载 其中一个问题是:不使用索引的Mysql查询,mysql,sql,Mysql,Sql,我在mysql中有一个相当大的订单表(大约120k行,并且还在增长),我在mysql慢速日志中看到一些查询花费的时间太长。 由于这个原因,我在服务器上也有一些峰值负载 其中一个问题是: SELECT [list of fields] FROM orders o LEFT JOIN orders_total ot ON ( o.orders_id = ot.orders_id ) LEFT JOIN orders_status s
SELECT [list of fields]
FROM orders o
LEFT JOIN orders_total ot
ON ( o.orders_id = ot.orders_id )
LEFT JOIN orders_status s
ON o.orders_status = s.orders_status_id
WHERE s.language_id = '3'
AND ot.class = 'ot_total'
AND ( o.customers_name LIKE '%126627%'
OR o.customers_company LIKE '%126627%'
OR o.orders_id LIKE '%126627%'
OR o.delivery_name LIKE '%126627%'
OR o.delivery_company LIKE '%126627%'
OR o.customers_email_address LIKE '%126627%'
OR o.customers_telephone LIKE '%126627%'
OR o.billing_name LIKE '%126627%'
OR o.billing_company LIKE '%126627%'
OR o.billing_nif LIKE '%126627%' )
ORDER BY o.orders_id DESC
LIMIT 0, 20;
对这些问题进行了解释,并得出以下结论:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE o index PRIMARY,order_status PRIMARY 4 NULL 127733 Using where
1 SIMPLE s eq_ref PRIMARY PRIMARY 8 o.orders_status,const 1 Using where
1 SIMPLE ot ref idx_orders_total_orders_id idx_orders_total_orders_id 4 o.orders_id 4 Using where
如您所见,查询正在遍历表订单的所有记录
表订单的状态为orders\u
index
如何避免这种情况?
它是一个MyISAM
表,将它变成InnoDB
将解决这个峰值负载问题
谢谢这可能无法修复您的查询,但是
左连接
s应该是内部的连接
s。无论如何,where
子句将它们转换为内部联接
请参阅此版本查询的解释:
SELECT [list of fields]
FROM orders o JOIN
orders_total ot
ONo.orders_id = ot.orders_id JOIN
orders_status s
ON o.orders_status = s.orders_status_id
WHERE s.language_id = '3' AND ot.class = 'ot_total' AND
(o.customers_name LIKE '%126627%' OR
o.customers_company LIKE '%126627%' OR
o.orders_id LIKE '%126627%' OR
o.delivery_name LIKE '%126627%' OR
o.delivery_company LIKE '%126627%' OR
o.customers_email_address LIKE '%126627%' OR
o.customers_telephone LIKE '%126627%' OR
o.billing_name LIKE '%126627%' OR
o.billing_company LIKE '%126627%' OR
o.billing_nif LIKE '%126627%'
)
ORDER BY o.orders_id DESC
LIMIT 0, 20;
注意:还要检查s.language_id
是字符串还是数字。如果是数字,请删除单引号。有时这些会影响优化
假设您有正确的索引(例如orders(orders\u id,status\u id)
,orders\u total(class,order\u id)
,order\u status(order\u id)
),仍有几种方法可以运行查询
因为除了扩展的like
子句之外还有其他条件,所以查询不必进行完整的表扫描。然而,一个大问题是,其他两个条件(阶级和地位)的选择性如何。我的猜测是,这些都不是很有选择性的——也就是说,超过1%的行符合这些条件。优化器决定扫描表是解决此查询的最有效方法
顺便说一下,类似于的情况看起来非常可疑。如果您正在字符字段中查找单词,则可以考虑全文搜索,这要快得多。字符串在该查询“代码>”中搜索…像“%126627%”这样的行是不可搜索的,因此如果有许多行与其他条件匹配,将导致糟糕的性能。您可能想考虑使用FultLeXT索引,或者像SoR或狮身人面像这样的搜索引擎。当左联接时,WHERE子句中的右表条件使外部联接工作作为内部连接,即将“S.LoalGracyID=3”改为ON子句,并且还移动“OT.Cype=OTyToTo”。(如果需要外部联接…!)所有条件列名称(如“%pattern%”)都使用完全扫描。如果您想提供帮助,您需要向我们展示一些附加信息,如表定义和实际sql查询的示例。正如jarlh所说,orders\u状态的外部连接,那么根据s.language\u id进行过滤是很奇怪的。订单数量和类别相同。这些左连接应该是内部连接,或者语言id和类条件应该是外部连接条件的一部分。解决方案实际上是规范化数据库,并创建另一个表,将WHERE子句中的模式中的所有id与orders表中的特定记录连接起来。