0

I have table "listing_data" which is about 150.000 rows. I have problem with filtering and sorting when the data comes from JSON. I have added keys on each column which needed for filtering and sorting.

However, as one column "data" used to store JSON use "TEXT" so I cannot add index there. I am trying to run this query

SELECT 
  id, 
  title, 
  slug, 
  description, 
  uniqueId, 
  data, 
  images, 
  view, 
  contact, 
  lastSync, 
  status, 
  sold, 
  waktu, 
  FLOOR(
    JSON_UNQUOTE(
      JSON_EXTRACT(data, '$.price')
    )/ 100000000
  )* 100 AS rangePrice, 
  COUNT(id) AS total 
FROM 
  listing_data 
WHERE 
  JSON_UNQUOTE(
    JSON_EXTRACT(data, '$.subCategory')
  )= 'rumah' 
  and JSON_UNQUOTE(
    JSON_EXTRACT(data, '$.type')
  )= 'dijual' 
  and LOWER(
    JSON_UNQUOTE(
      JSON_EXTRACT(data, '$.province')
    )
  )= 'lampung' 
  and LOWER(
    JSON_UNQUOTE(
      JSON_EXTRACT(data, '$.regency')
    )
  )= 'bandar lampung' 
  and LOWER(
    JSON_UNQUOTE(
      JSON_EXTRACT(data, '$.district')
    )
  )= 'way halim' 
GROUP BY 
  JSON_UNQUOTE(
    JSON_EXTRACT(data, '$.price')
  ) 
ORDER BY 
  rangePrice ASC 
LIMIT 
  0, 20

It took 2.8148 seconds to run. Is there any solution how to make it faster? I want to know if there is a way to add index into TEXT column.

1
  • In MySQL 5.7 and higher you can make indexes on generated columns. But the index must be for those specific columns. It wouldn't be suitable if the JSON fields you search for are changing all the time, and I am guessing they will be. Commented Mar 27, 2021 at 7:38

2 Answers 2

2

You could extract all needed data from the JSON column and put it in new columns.

These new columns can be of types that can be indexed.

Perhaps you can even get rid of the JSON column completely?

Sign up to request clarification or add additional context in comments.

Comments

1
  • LOWER gets in the way of optimization. Use a suitable collation.
  • JSON_UNQUOTE gets in the way of optimization; why do you need it?
  • Pull out commonly used columns (especially price or rangeprice, and general geographic area, probably also type) into their own columns.
  • Then build selected 'composite' indexes on them
  • The GROUP BY is invalid since it does not include various other columns. Perhaps that needs to be a separate query or a second pass over the data.
  • Use COUNT(*) instead of COUNT(id); the latter requires unnecessarily testing id IS NOT NULL.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.