[MDEV-25196] Slow Query, when using LOCATE String Function Created: 2021-03-19  Updated: 2021-03-23  Resolved: 2021-03-23

Status: Closed
Project: MariaDB Server
Component/s: Optimizer
Affects Version/s: 10.5.9
Fix Version/s: N/A

Type: Bug Priority: Major
Reporter: Wayne Forrest Assignee: Sergei Golubchik
Resolution: Not a Bug Votes: 0
Labels: generated, locate, slow
Environment:

MacOS BigSur 11.2.3 (20D91)



 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);



 Comments   
Comment by Sergei Golubchik [ 2021-03-23 ]

The server cannot use indexes for a column used in LOCATE(). Generated or not. If your only condition is LOCATE it'll mean a full table scan.

Generated at Thu Feb 08 09:35:52 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.