Details
Description
I have a MariaDB Generated column and when using LOCATE to query the field, the query is slow, examining all the rows.
SELECT attr_client_name
|
FROM tbl
|
WHERE (LOCATE(attr_client_name, "joe70700") > 0); |
# Time: 210319 14:19:04 |
# User@Host: admin[admin] @ localhost [127.0.0.1] |
# Thread_id: 18 Schema: test_slow QC_hit: No |
# Query_time: 0.021040 Lock_time: 0.000110 Rows_sent: 5 Rows_examined: 100000 |
# Rows_affected: 0 Bytes_sent: 152 |
CREATE TEST TABLE
# CREATE TEST TABLE
|
|
DROP TABLE IF EXISTS tbl;
|
CREATE TABLE tbl (
|
Id bigint(20) NOT NULL AUTO_INCREMENT, |
ClientDocument longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(ClientDocument)),
|
attr_client_name varchar(255) GENERATED ALWAYS AS (json_value(ClientDocument,'$.Name')) STORED, |
PRIMARY KEY (`Id`),
|
KEY idx_tbl_name (attr_client_name)
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
CREATE TEST PROCEDURE
# CREATE TEST PROCEDURE
|
DROP PROCEDURE IF EXISTS tbl_fill_json;
|
CREATE PROCEDURE tbl_fill_json (IN cnt int) |
BEGIN
|
DECLARE
|
p1 int DEFAULT 0; |
DECLARE
|
val longtext;
|
label1: LOOP
|
SET p1 = p1 + 1; |
SET val = concat('{"Name":', '"Joe', p1, '"', '}'); |
IF p1 <= cnt THEN
|
|
INSERT INTO tbl (ClientDocument)
|
VALUES(val);
|
|
ITERATE label1;
|
END IF;
|
LEAVE label1;
|
END LOOP label1;
|
END;
|
STORE 100,000 Records
# STORE 100,000 Records |
call tbl_fill_json(100000); |
TEST QUERY 1
# TEST QUERY 1 |
|
explain
|
SELECT attr_client_name
|
FROM tbl
|
WHERE (LOCATE(attr_client_name, "joe70700") > 0); |
TEST QUERY 2
# TEST QUERY 2 |
|
explain
|
SELECT attr_client_name
|
FROM tbl
|
WHERE attr_client_name LIKE 'joe70700'; |
CORRECTION
_I have realised that I have used the LOCATE function incorrect below, however this does not explain why the queries are slow;
The correct LOCATE usage should swap the text literal with the column name being the second argumant. e.g.
_
The correct usage of LOCATE
explain
|
SELECT attr_client_name
|
FROM tbl
|
WHERE (LOCATE("joe70700", attr_client_name) > 0); |