我在mysql中有一个非常大的订单表(大约120k行,并且正在增长),我在mysql-slow日志中看到一些查询花了太长时间。 此外,由于这个原因,我在服务器中有一些峰值负载。
其中一个问题:
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_status
索引。
怎么能避免这个?
它是一个MyISAM
表,使其成为InnoDB
将解决此峰值负载?
由于
答案 0 :(得分:0)
这可能无法修复您的查询,但left join
应该是内部join
。无论如何,它们都被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_id, status_id)
,orders_total(class, order_id)
,order_status(order_status_id)
),则仍有多种方法可以运行查询。
由于除了广泛的like
子句之外还有其他条件,因此查询不会 进行全表扫描。但是,一个很大的问题是,其他两个条件(类和状态)的选择性如何。我的猜测是这些不是很有选择性 - 即超过1%的行符合这些条件。优化器决定扫描表是解决此查询的最有效方法。
顺便说一下,like
条件看起来非常可疑。如果您正在寻找字符字段中的单词,您可以考虑全文搜索,这要快得多。