将 MySQL 表分成 2 个?当前搜索速度太慢

发布于 2025-01-03 16:13:00 字数 2200 浏览 3 评论 0原文

我正在使用 MySQL 表来存储用户将搜索的地图上的事物数据。该网站允许用户添加额外的过滤器来缩小结果范围。

主 MySQL 查询:

SELECT listing_id, listings.property_1, property_2, address_1, address_2, city, listings.lat, listings.lng, img_subpath, photos, some_timestamp
    FROM table
    WHERE listings.lat BETWEEN 61.123 AND 61.124
    AND listings.lng BETWEEN 40.123 AND 40.124
    AND some_timestamp BETWEEN DATE_SUB( NOW(), INTERVAL 0 DAY) AND DATE_SUB( NOW(), INTERVAL 5 DAY)')
    JOIN (SELECT price, lat, lng, MAX(some_timestamp) as latest FROM listings GROUP BY price, lat, lng) as t2', 'listings.price=t2.price AND listings.lat=t2.lat AND listings.lng=t2.lng AND listings.some_timestamp=t2.latest', 'inner')
    LIMIT 200,0

列:

(索引列以粗体显示)

(以 property_ 开头的列除前 2 个之外都是可选过滤器)

  • listing_id int(8)
  • url varchar(255)
  • city varchar(32)
  • somename varchar(32)
  • price int(7)
  • price_per int(7)
  • property_1 int(2)
  • property_2 int(2)
  • address_1 varchar(255)
  • address_2 carchar(255)
  • city varchar(64 )
  • state varchar(32)
  • postal int(6)
  • some_timestamp 时间戳
  • another_timestamp 时间戳
  • lat float(10)
  • lng float(10)
  • 描述文本
  • img_subpath varchar(15)
  • 照片文本
  • reply_email varchar(255)
  • 电话 varchar(16)
  • property_3 tinyint(1)
  • property_4 tinyint(1)
  • property_5 tinyint(1)
  • property_6 tinyint(1)
  • property_7 tinyint(1)
  • property_8 tinyint(1)
  • property_9 tinyint(1)
  • property_10 tinyint(1)
  • property_11tinyint(1)
  • property_12tinyint(1)
  • property_13tinyint(1)
  • property_14tinyint(1)

问题数据库获取结果的时间过长(3-4秒)。如何才能将其速度加快到 <0.5 秒,这在非常相似的网站上已经完成了?

如果我有 2 个表,第一个表将仅包含搜索中涉及的列,下一个表包含所有其他列。因此,当搜索发生时,它会搜索第一个表,获取结果的 listing_id,然后使用 IN 子句从第二个表中检索所有其他数据?

请指教,谢谢!

I am using a MySQL table to store data of things on a map which will be searched by the user. The site allows the user to add in additional filters to narrow his results.

Main MySQL Query:

SELECT listing_id, listings.property_1, property_2, address_1, address_2, city, listings.lat, listings.lng, img_subpath, photos, some_timestamp
    FROM table
    WHERE listings.lat BETWEEN 61.123 AND 61.124
    AND listings.lng BETWEEN 40.123 AND 40.124
    AND some_timestamp BETWEEN DATE_SUB( NOW(), INTERVAL 0 DAY) AND DATE_SUB( NOW(), INTERVAL 5 DAY)')
    JOIN (SELECT price, lat, lng, MAX(some_timestamp) as latest FROM listings GROUP BY price, lat, lng) as t2', 'listings.price=t2.price AND listings.lat=t2.lat AND listings.lng=t2.lng AND listings.some_timestamp=t2.latest', 'inner')
    LIMIT 200,0

Columns:

(Indexed columns are in bold)

(columns that start with property_ are optional filters except the first 2)

  • listing_id int(8)
  • url varchar(255)
  • city varchar(32)
  • somename varchar(32)
  • price int(7)
  • price_per int(7)
  • property_1 int(2)
  • property_2 int(2)
  • address_1 varchar(255)
  • address_2 carchar(255)
  • city varchar(64)
  • state varchar(32)
  • postal int(6)
  • some_timestamp timestamp
  • another_timestamp timestamp
  • lat float(10)
  • lng float(10)
  • description text
  • img_subpath varchar(15)
  • photos text
  • reply_email varchar(255)
  • phone varchar(16)
  • property_3 tinyint(1)
  • property_4 tinyint(1)
  • property_5 tinyint(1)
  • property_6 tinyint(1)
  • property_7 tinyint(1)
  • property_8 tinyint(1)
  • property_9 tinyint(1)
  • property_10 tinyint(1)
  • property_11 tinyint(1)
  • property_12 tinyint(1)
  • property_13 tinyint(1)
  • property_14 tinyint(1)

Problem: The database takes too long (3-4seconds) to fetch the results. How can it be sped up to <0.5sec which has been done on very similar sites?

Should I have 2 tables, the first table will contain only columns involved in the search, and the next table contains all the other columns. So when the search happens, it searches the first table, gets the listing_id of the results, then use a IN clause to retrieve all the other data from the second table?

Please advise, thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

听风吹 2025-01-10 16:13:00

我认为您正在尝试通过以下方式获取过去五天的时间戳:

AND some_timestamp BETWEEN DATE_SUB( NOW(), INTERVAL 0 DAY)
AND DATE_SUB( NOW(), INTERVAL 5 DAY)')

如果是这种情况,它应该与以下内容相同

AND some_timestamp BETWEEN DATE_SUB(NOW(), INTERVAL 5 DAY)) AND NOW()

如果您没有带有 some_timestamp 且具有未来值的记录,您

AND some_timestamp > DATE_SUB(NOW(), INTERVAL 5 DAY))

现在可以使用,我认为这应该工作得更快

SELECT listing_id, listings.property_1, property_2, address_1, address_2, city,
    listings.lat, listings.lng, img_subpath, photos, some_timestamp
FROM t2
LEFT JOIN listings
    ON (listings.price=t2.price AND listings.lat=t2.lat AND listings.lng=t2.lng
        AND t2.some_timestamp < listings.some_timestamp)
WHERE listings.lat BETWEEN 61.123 AND 61.124
    AND listings.lng BETWEEN 40.123 AND 40.124
    AND some_timestamp BETWEEN DATE_SUB(NOW(), INTERVAL 5 DAY)) AND NOW()
    AND t2.some_timestamp is null
LIMIT 200

PS:我不认为拆分表会提高性能太多...实际上,如果您必须连接两个表才能获得结果,则需要更多时间

I think you're trying to get the timestamps of the last five days with this:

AND some_timestamp BETWEEN DATE_SUB( NOW(), INTERVAL 0 DAY)
AND DATE_SUB( NOW(), INTERVAL 5 DAY)')

If that is the case, it should be the the same as

AND some_timestamp BETWEEN DATE_SUB(NOW(), INTERVAL 5 DAY)) AND NOW()

And if you don't have records with some_timestamp with a future value you can use

AND some_timestamp > DATE_SUB(NOW(), INTERVAL 5 DAY))

Now, I THINK this should work faster

SELECT listing_id, listings.property_1, property_2, address_1, address_2, city,
    listings.lat, listings.lng, img_subpath, photos, some_timestamp
FROM t2
LEFT JOIN listings
    ON (listings.price=t2.price AND listings.lat=t2.lat AND listings.lng=t2.lng
        AND t2.some_timestamp < listings.some_timestamp)
WHERE listings.lat BETWEEN 61.123 AND 61.124
    AND listings.lng BETWEEN 40.123 AND 40.124
    AND some_timestamp BETWEEN DATE_SUB(NOW(), INTERVAL 5 DAY)) AND NOW()
    AND t2.some_timestamp is null
LIMIT 200

PS: I don't think splitting the table would improve performance much... actually, if you have to join both tables to get a result, it'll take more

初与友歌 2025-01-10 16:13:00

您所提出的在某种程度上是索引如何工作背后的理论。速度减慢很可能是由于加入聚合子选择造成的。我建议预先聚合该信息(无法立即看到任何不能这样做的原因)并针对该表进行联接。

What you're proposing is somewhat the theory behind how indexes work. Most likely the slow down is coming from joining the aggregated subselect. I'd suggest pre-aggregating that information ( can't see offhand any reason why you can't ) and the joining against that table.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文