-1

目前我有 13 个表,每个表大约 5-6 列。在 13 个表中,4 个表的行数超过 200,000(20 万)行,其中 5-6 列具有 varchar(1000) 或更多值。其余 10 个表有大约 10000 行,每列 5-6 列,每列具有 varchar(1000) 或更多值。每当我编写包含来自 >=3 表的数据的查询时,预期结果为 1000 行和 5 列时,查询执行会花费大量时间,大约(30 分钟到 2 小时)。

我有大约 12GB RAM 和 x86_64 x86_64 x86_64 GNU/Linux 的系统。

有哪些可能的方法可以大幅减少查询执行时间?

select a.d_id, 
       a.d_n, 
       a.t_id, a.act, 
       a.pm, 
       b.d_t, 
       b.d_d, 
       b.pm, 
       b.mec_of_act, 
       b.d_g, 
       b.d_c, 
       c.n_id, 
       c.s_name, 
       c.s_status, 
       c.s_p, 
       c.dis 
from    d_tar a, 
       d_char b, 
       ct c, 
       c_int d, 
       d_s e,
       d_b f 
where   a.d_id=b.d_id 
&&      a.d_id=e.d_id 
&&      t_id='847' 
&&      a.d_id=f.d_id 
&&      d.n_id=c.n_id 
&&      (d.in_name=b.d_n 
          or d.in_name=e.snym 
          or d.in_name=f.b_name);
4

2 回答 2

0

这绝对是基本的,所以我相信你已经做到了。但以防万一,请务必在您的 my.ini 文件中设置查询日志,并查看您的索引是否始终设置正确。

log_queries_not_using_indexes = 1  
slow_query_log = 1
slow_query_log_file = "E:/wamp/logs/slowquery.log"
于 2013-10-11T08:39:21.220 回答
0

您加入的字段是索引数据类型和类似数据类型吗?

此外,查看您的查询,您似乎正在基于几个表之间的 OR 进行连接,我怀疑这可能会阻止 MySQL 有效地使用索引。

尝试使用显式连接,这会使连接更加明显,并为其发布 EXPLAIN:-

SELECT a.d_id, 
       a.d_n, 
       a.t_id, 
       a.act, 
       a.pm, 
       b.d_t, 
       b.d_d, 
       b.pm, 
       b.mec_of_act, 
       b.d_g, 
       b.d_c, 
       c.n_id, 
       c.s_name, 
       c.s_status, 
       c.s_p, 
       c.dis 
FROM d_tar a
INNER JOIN d_char b ON a.d_id=b.d_id 
INNER JOIN d_b f ON a.d_id=f.d_id 
INNER JOIN d_s e ON a.d_id=e.d_id 
INNER JOIN c_int d ON d.in_name IN (b.d_n, e.snym, f.b_name)
INNER JOIN ct c ON d.n_id=c.n_id 
WHERE   a.t_id='847' 

编辑 - 如果不同列名上的连接阻止使用有用的索引,那么以下可能会起作用(尽管这假设 c_int.n_id 是唯一的): -

SELECT a.d_id, 
       a.d_n, 
       a.t_id, 
       a.act, 
       a.pm, 
       b.d_t, 
       b.d_d, 
       b.pm, 
       b.mec_of_act, 
       b.d_g, 
       b.d_c, 
       CASE WHEN c1.n_id IS NOT NULL THEN c1.n_id WHEN c2.n_id IS NOT NULL THEN c2.n_id WHEN c3.n_id IS NOT NULL THEN c3.n_id END AS n_id,
       CASE WHEN c1.n_id IS NOT NULL THEN c1.s_name WHEN c2.n_id IS NOT NULL THEN c2.s_name WHEN c3.n_id IS NOT NULL THEN c3.s_name END AS s_name,
       CASE WHEN c1.n_id IS NOT NULL THEN c1.s_status WHEN c2.n_id IS NOT NULL THEN c2.s_status WHEN c3.n_id IS NOT NULL THEN c3.s_status END AS s_status,
       CASE WHEN c1.n_id IS NOT NULL THEN c1.s_p WHEN c2.n_id IS NOT NULL THEN c2.s_p WHEN c3.n_id IS NOT NULL THEN c3.s_p END AS s_p,
       CASE WHEN c1.n_id IS NOT NULL THEN c1.dis WHEN c2.n_id IS NOT NULL THEN c2.dis WHEN c3.n_id IS NOT NULL THEN c3.dis END AS dis
FROM d_tar a
INNER JOIN d_char b ON a.d_id = b.d_id 
INNER JOIN d_b f ON a.d_id = f.d_id 
INNER JOIN d_s e ON a.d_id = e.d_id 
LEFT JOIN c_int d1 ON d1.in_name = b.d_n
LEFT JOIN c_int d2 ON d2.in_name = e.snym
LEFT JOIN c_int d3 ON d3.in_name = f.b_name
LEFT JOIN ct c1 ON d1.n_id = c1.n_id 
LEFT JOIN ct c2 ON d1.n_id = c2.n_id 
LEFT JOIN ct c3 ON d1.n_id = c3.n_id 
WHERE   a.t_id='847' 
AND (c1.n_id IS NOT NULL
OR c2.n_id IS NOT NULL
OR c2.n_id IS NOT NULL)
于 2013-10-11T09:30:10.327 回答