我有一个包含 500 万行的表
CREATE TABLE dummy_table (
num VARCHAR(16) NOT NULL DEFAULT 0,
rsid VARCHAR(16) NOT NULL,
list VARCHAR(128) NOT NULL,
PRIMARY KEY (num, rsid)
);
表中的num
字段是某个动态数字的前缀(上面查询中的“123457467890”)。现在我需要获取list
基于num
和rsid
的列,其中num
必须是来电号码的最长前缀匹配。为了获取 list
我有一个以下查询:
select list
from dummy_table
where '123457467890' like CONCAT(num, '%')
and rsid = '123'
order by LENGTH(num) desc LIMIT 1;
注意:123457467890`:每次我们抛出查询时该数字都会不同
现在的问题是执行这个查询,MYSQL 大约需要 0.80 秒,这对我来说非常长。我需要在一秒钟内抛出超过 1000 个查询。有什么办法可以优化这个查询到这个程度吗?谁能帮助实现这个结果?
最佳答案
我的第一个优化是:
- 添加另一列“长度”
- 在(rsid, length DESC, num)
现在您的查询仅略有不同:
- 从 dummy_table 中选择列表,其中 '123457467890' LIKE CONCAT(num, '%') AND rsid = '123' ORDER BY length DESC LIMIT 1;
但是,通过在索引中包含长度,查询应该能够在第一次命中时停止。
但是...
这始终是一个代价高昂的过程。最坏的情况是您找不到匹配项 - 因此无论如何都必须扫描完整的 (rsid = '123') 记录集。
上述优化不会帮助优化最坏的情况,只能帮助优化最好的情况。 (比赛时间越长,帮助越大,但对于较短的比赛帮助不大。)
你可能被迫做的事情是……
1.创建临时表
2. 在其中插入“1234567890”
3. 在其中插入“123456789”
4. 在其中插入“12345678”
.
.
.
名词在其中插入“1”
此时,临时表中的搜索字符串已具有所有可能的匹配项。
然后您的查询可以使用索引查找。可能会找到 10 个匹配项(在本例中),然后找到其中最长的一个。
-- Index now needs to be (rsid, num, length)
SELECT
*
FROM
dummy_table
INNER JOIN
your_search_table
ON dummy_table.num = your_search_table.num
WHERE
rsid = '123'
ORDER BY
dummy_table.length
LIMIT
1
关于mysql - 500万行表中最长前缀匹配的最佳MYSQL查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20703660/