以下查询有效,但10个记录(2秒)非常慢。分析说它创建了一个tmp表,但我不确定原因。
基本上,我正在加入当前用户,加入acl小组,以获取他们所在的所有群组,然后将小组加入公司,获取他们所在的所有公司,然后将公司加入订单,得到所有订单..
如果我删除此行
ORDER BY orders.created_on DESC
然后查询在0.06秒内执行(更可接受)..
帮助,关于如何优化的任何想法?非常感谢:))
SELECT
orders.uuid,
companies.name as company_name
FROM
users u
JOIN
users_acl_groups g on u.uuid = g.user_uuid
JOIN
users_acl acl on (acl.user_uuid = u.uuid or acl.group_uuid = g.group_uuid)
JOIN
companies on acl.item_uuid = companies.uuid
JOIN
orders on companies.uuid = orders.company_uuid
WHERE
u.uuid = 'DDEC8073-5056-C000-01ED583A51CBCA32' and orders.status <> ''
ORDER BY orders.created_on DESC
limit 0, 10;
更新,查询的解释..
1 SIMPLE命令所有9403使用 临时;使用filesort
1 SIMPLE acl ALL 1859使用where; 使用连接缓冲区
1 SIMPLE g ALL 2005使用where; 使用连接缓冲区
1 SIMPLE公司eq_ref PRIMARY PRIMARY 52 table.orders.company_uuid 1
1 SIMPLE u ALL 33595使用where; 不同;使用连接缓冲区
答案 0 :(得分:2)
您是否考虑过将 fact table 样式设计作为非规范化步骤?
基本上它是一种多对多的交集表,例如:
CREATE TABLE user_order_fact (
user_uuid ...
order_uuid ...
order_created_on ...
order_status ...
company_name ...,
primary key (user_uuid, order_uuid),
key (user_uuid, order_status, order_created_on, order_uuid, company_name)
);
... fill with data ...
SELECT
order_uuid,
company_name
FROM
user_order_fact
WHERE
user_uuid = 'DDEC8073-5056-C000-01ED583A51CBCA32' and order_status <> ''
ORDER BY order_created_on DESC
limit 0, 10;
我在猜测复合指数。你必须进行实验,直到你做对了。基本上你正试图让优化器计划报告使用索引。
当然这是以冗余方式存储数据并以非规范化形式存储,因此您需要设置一些触发器以使其与规范化表保持同步。
答案 1 :(得分:0)
确保“orders.created_on”有一个索引......如果确实如此,那么Bill在顶部的方法将是最好的,但需要一些工作。
答案 2 :(得分:0)
如果不了解现有索引或每个表的数量,很难回答。
此外,没有关于模型的大量信息......查询是否会返回所有结果?
所有用户都属于某个群组吗?似乎不是......并且查询不会返回组外的用户。
组是否可以属于某个组,需要递归查询?
答案 3 :(得分:0)
我不确定它的确切原因可能需要2秒。这个查询获取10条记录是不可能的,但这里看到的是
acl.user_uuid = u.uuid or acl.group_uuid = g.group_uuid
基于UID的加入,也许你也是 用它作为主键 上面回答。
ORDER BY orders.created_on
。在Order by
上使用date
不会比使用PK或任何整数值更优化
更合适。
orders.status <> ''
如果在表上使用任何索引,则没有索引
可以在此查询中使用,因为
不是运营商和类似
在任何查询中使用时,运算符不使用索引。
我认为主要的贡献因素是在联接中使用UID 因此,您的查询中可以看到所有三个避免条件,这可能会使您的查询变得懒惰
答案 4 :(得分:0)
很少有想法:
您实际上没有在查询中选择orders.created_on
。所以没有必要对该列进行排序。也许,选择它(SELECT orders.created_on
...)会有助于表现(只是猜测 - 我不知道我在这里说什么)。
如果查询返回的记录数量不足,您可以随时在应用程序中进行排序。
有时使用N个小查询而不是1个大sql查询会更明智。伪代码:
user_id = get_one("SELECT uuid FROM users WHERE ...");
group_ids = get_many("SELECT uuid FROM groups WHERE user_uuid = " + user_id);
comps_ids = get_many("SELECT DISTINCT item_uuid FROM acls WHERE user_uuid = " + user_id + " OR group_uuid IN " + groups_ids.to_q());
orders = get_many("SELECT * FROM orders WHERE company_uuid IN " + comps_ids.as_q() + " WHERE status <> '' ORDER BY created_on");