简体   繁体   English

SQL 查询优化 - 来自另一个表的多行

[英]SQL query optimization - multiple rows from another table

I have my tables like this (currently)我有这样的桌子(目前)

CREATE TABLE `users` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(64) DEFAULT NULL,
  PRIMARY KEY (`id`)
);

CREATE TABLE `user_opts` (
  `user_id` bigint(20) NOT NULL,
  `opt1` varchar(64) DEFAULT NULL,
  `opt2` TINYINT(4) DEFAULT NULL,
  `opt3` varchar(64) DEFAULT NULL,
  KEY `user_id_idx` (`user_id`)
);

I want to be able to do queries like this:我希望能够进行这样的查询:

SELECT DISTINCT name
FROM users
WHERE 
    id = 1 AND (
        EXISTS ( SELECT 1 FROM user_opts WHERE user_opts.user_id = users.id AND user_opts.opt1 = 'a' AND user_opts.opt3 = 'c') OR
        EXISTS ( SELECT 1 FROM user_opts WHERE user_opts.user_id = users.id AND user_opts.opt1 = 'b' AND user_opts.opt2 = 1)
    );

and this:和这个:

SELECT DISTINCT name
FROM users
WHERE 
    id = 1 AND (
        EXISTS ( SELECT 1 FROM user_opts WHERE user_opts.user_id = users.id AND user_opts.opt1 = 'a' AND user_opts.opt3 = 'e') AND
        EXISTS ( SELECT 1 FROM user_opts WHERE user_opts.user_id = users.id AND user_opts.opt1 = 'b' AND user_opts.opt2 = 1)
    );

The obvious problem I'm starting to have is that the more users the queries goes slower and slower.我开始遇到的一个明显问题是,用户越多,查询的速度就越慢。 I know I could refactor the first type of the queries (using OR ) by JOINing the table, but the JOIN itself would be slow since I can't have a PK on the user_opts table.我知道我可以通过 JOIN 表重构第一种类型的查询(使用OR ),但是 JOIN 本身会很慢,因为我不能在user_opts表上进行 PK。

How could I restructure my data (and the queries) so I can do efficient/fast searches?我怎样才能重组我的数据(和查询),以便我可以进行高效/快速的搜索? Preferably, if possible, I would like to keep the same queries for both AND and OR types, just switching the condition between the two.最好,如果可能的话,我想对ANDOR类型保持相同的查询,只是在两者之间切换条件。

DB Fiddle url DB小提琴 url

Thanks!谢谢!

You can use aggregation:您可以使用聚合:

select user_id
from user_opts uo
where opt3 = 'c' or opt2 = 1
group by user_id
having sum(opt3 = 'c') >= 1 and
       sum(opt2 = 1) >= 1;

This handles the case when the two options are set on the same row in user_opts .当两个选项设置在user_opts的同一行时,这将处理这种情况。

Adding these two indexes would speed up the EXISTS :添加这两个索引将加快EXISTS

INDEX(user_id, opt1, opt3)
INDEX(user_id, opt1, opt2)

Your schema is a variant on EAV, which is notoriously inefficient and clumsy.您的架构是 EAV 的变体,众所周知,它效率低下且笨拙。 Is there a good reason not to have opt2 and opt3 in users ? users中有没有 opt2 和 opt3 的充分理由?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM