Select 包含所有指示值的 ID(通配符冲突问题)MariaDB
Select id's containing all indicated Values (Wildcard collisions problem) MariaDB
有问题的 table (10.1.29-MariaDB):
[Table] => blog_search
[Create Table] => CREATE TABLE `blog_search` (
`bkey` varchar(28) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`blog_id` int(10) unsigned NOT NULL,
`follows` int(10) unsigned NOT NULL,
UNIQUE KEY `bkey` (`bkey`,`blog_id`),
UNIQUE KEY `blog_id` (`blog_id`,`bkey`) USING BTREE,
KEY `bkey_follows` (`bkey`,`follows`,`blog_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
bkey
是博客标题中使用的一个词。 follows
数据将在每个博客的每个词中重复。
我有一个 Select 在没有通配符的情况下工作得很好(数据库选择的键=>bkey_follow
):
SELECT blog_id
FROM blog_search
WHERE bkey = 'news' OR bkey = 'usa'
GROUP BY blog_id
HAVING COUNT(*) > 1
ORDER BY FOLLOWS DESC
LIMIT 30
但是当我使用通配符时(key=>bkey
由数据库选择):
WHERE bkey LIKE 'news%' OR bkey LIKE 'usa%'
它仍然可以进行索引搜索,但是“news”和“newsletter”关键字将匹配为 COUNT( *) = 2,但它不会找到 'usa'
我做了这个新查询,它按我想要的方式工作,但是如果最后一个词有很多结果,查询就会变得很慢(因为查询是从后到前执行的,并且必须读取 100% 的结果index) (key=>blog_id
由数据库选择):
SELECT blog_id
FROM blog_search
WHERE
blog_id IN (SELECT blog_id FROM blog_search WHERE bkey LIKE 'news%')
AND blog_id IN (SELECT blog_id FROM blog_search WHERE bkey LIKE 'usa%')
GROUP BY blog_id
ORDER BY follows DESC
LIMIT 30
如果我 FORCE INDEX (bkey)
甚至更好 FORCE INDEX (bkey_follows)
它会提高一点点,比如 35%,但仍然比我认为应该可能的速度慢 10 倍。
我想要一个没有 sub-queries 的更优化的查询。像这样的 WRONG 查询,(但正确的版本):
SELECT blog_id, 0 AS dist1, 0 AS dist2
FROM blog_search
WHERE ( bkey LIKE 'news%' AND 1=dist1=1 )
OR ( bkey LIKE 'usa%' AND 1=dist2=1 )
GROUP BY blog_id
HAVING (dist1=1 AND dist2=1)
ORDER BY follows DESC
LIMIT 30
其他数据:我正在开发 blogs/posts 标题的搜索。我尝试了很多东西:Regex、LIKE %...% 和 FULLTEXT 索引,我 "approved" 将其用于关联排序结果。更有前途的搜索是这个问题中讨论的搜索,因为它的速度和按 'follows'.
排序结果的速度是最好的
您可以将 having
子句表述为:
SELECT blog_id
FROM blog_search
WHERE bkey LIKE 'news%' OR bkey = 'usa%'
GROUP BY blog_id
HAVING SUM( bkey LIKE 'news%' ) > 0 AND
SUM( bkey LIKE 'usa%' ) > 0
ORDER BY FOLLOWS DESC
LIMIT 30
在聚合之前进行过滤的一种便捷方式是使用正则表达式:
SELECT blog_id
FROM blog_search
WHERE bkey REGEXP 'news|use'
GROUP BY blog_id
HAVING SUM( bkey LIKE 'news%' ) > 0 AND
SUM( bkey LIKE 'usa%' ) > 0
ORDER BY FOLLOWS DESC
LIMIT 30
您不关心有多少行匹配。许多其他解决方案会导致 "explode-implode" 综合症。那是您收集大量行的地方,只是后来通过 GROUP BY
归结为几行。这通过使用 "semi-join"、EXISTS
.
避免了一半
SELECT DISTINCT blog_id
FROM blog_search AS o
WHERE WHERE bkey LIKE 'news%'
AND EXISTS ( SELECT blog_id FROM blog_search
WHERE bkey LIKE 'usa%'
AND blog_id = o.blog_id )
ORDER BY follows DESC
LIMIT 30
有问题的 table (10.1.29-MariaDB):
[Table] => blog_search
[Create Table] => CREATE TABLE `blog_search` (
`bkey` varchar(28) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`blog_id` int(10) unsigned NOT NULL,
`follows` int(10) unsigned NOT NULL,
UNIQUE KEY `bkey` (`bkey`,`blog_id`),
UNIQUE KEY `blog_id` (`blog_id`,`bkey`) USING BTREE,
KEY `bkey_follows` (`bkey`,`follows`,`blog_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
bkey
是博客标题中使用的一个词。 follows
数据将在每个博客的每个词中重复。
我有一个 Select 在没有通配符的情况下工作得很好(数据库选择的键=>bkey_follow
):
SELECT blog_id
FROM blog_search
WHERE bkey = 'news' OR bkey = 'usa'
GROUP BY blog_id
HAVING COUNT(*) > 1
ORDER BY FOLLOWS DESC
LIMIT 30
但是当我使用通配符时(key=>bkey
由数据库选择):
WHERE bkey LIKE 'news%' OR bkey LIKE 'usa%'
它仍然可以进行索引搜索,但是“news”和“newsletter”关键字将匹配为 COUNT( *) = 2,但它不会找到 'usa'
我做了这个新查询,它按我想要的方式工作,但是如果最后一个词有很多结果,查询就会变得很慢(因为查询是从后到前执行的,并且必须读取 100% 的结果index) (key=>blog_id
由数据库选择):
SELECT blog_id
FROM blog_search
WHERE
blog_id IN (SELECT blog_id FROM blog_search WHERE bkey LIKE 'news%')
AND blog_id IN (SELECT blog_id FROM blog_search WHERE bkey LIKE 'usa%')
GROUP BY blog_id
ORDER BY follows DESC
LIMIT 30
如果我 FORCE INDEX (bkey)
甚至更好 FORCE INDEX (bkey_follows)
它会提高一点点,比如 35%,但仍然比我认为应该可能的速度慢 10 倍。
我想要一个没有 sub-queries 的更优化的查询。像这样的 WRONG 查询,(但正确的版本):
SELECT blog_id, 0 AS dist1, 0 AS dist2
FROM blog_search
WHERE ( bkey LIKE 'news%' AND 1=dist1=1 )
OR ( bkey LIKE 'usa%' AND 1=dist2=1 )
GROUP BY blog_id
HAVING (dist1=1 AND dist2=1)
ORDER BY follows DESC
LIMIT 30
其他数据:我正在开发 blogs/posts 标题的搜索。我尝试了很多东西:Regex、LIKE %...% 和 FULLTEXT 索引,我 "approved" 将其用于关联排序结果。更有前途的搜索是这个问题中讨论的搜索,因为它的速度和按 'follows'.
排序结果的速度是最好的您可以将 having
子句表述为:
SELECT blog_id
FROM blog_search
WHERE bkey LIKE 'news%' OR bkey = 'usa%'
GROUP BY blog_id
HAVING SUM( bkey LIKE 'news%' ) > 0 AND
SUM( bkey LIKE 'usa%' ) > 0
ORDER BY FOLLOWS DESC
LIMIT 30
在聚合之前进行过滤的一种便捷方式是使用正则表达式:
SELECT blog_id
FROM blog_search
WHERE bkey REGEXP 'news|use'
GROUP BY blog_id
HAVING SUM( bkey LIKE 'news%' ) > 0 AND
SUM( bkey LIKE 'usa%' ) > 0
ORDER BY FOLLOWS DESC
LIMIT 30
您不关心有多少行匹配。许多其他解决方案会导致 "explode-implode" 综合症。那是您收集大量行的地方,只是后来通过 GROUP BY
归结为几行。这通过使用 "semi-join"、EXISTS
.
SELECT DISTINCT blog_id
FROM blog_search AS o
WHERE WHERE bkey LIKE 'news%'
AND EXISTS ( SELECT blog_id FROM blog_search
WHERE bkey LIKE 'usa%'
AND blog_id = o.blog_id )
ORDER BY follows DESC
LIMIT 30