У меня есть два запроса MySQL, которые один за другим, бежать очень быстро:Как объединить эти два запроса mysql, чтобы сохранить его скорость?
QUERY 1
SELECT Ads.AdId FROM Ads, AdsGeometry WHERE
AdsGeometry.AdId = Ads.AdId AND
(ST_CONTAINS(GeomFromText('Polygon((
-4.9783515930176 36.627100703563,
-5.0075340270996 36.61222072018,
-4.9896812438965 36.57638676015,
-4.965991973877 36.579419508882,
-4.955005645752 36.617732160006,
-4.9783515930176 36.627100703563
))'), AdsGeometry.GeomPoint))
GROUP BY Ads.AdId
Этот запрос выполняется в 0,0013 секунды, и возвращает 4 строки.
QUERY 2
SELECT Ads.AdId FROM Ads, AdsHierarchy WHERE
Ads.AdId = AdsHierarchy.ads_AdId AND
AdsHierarchy.locations_LocationId = 148022797
GROUP BY Ads.AdId
Этот запрос выполняется в 0,0094 секунд, и возвращает 67 строк (3 из них одинаковы вышеуказанного запроса).
Я пытаюсь объединить эти два запроса в один запрос, потому что позже набор результатов из двух запросов должен быть упорядочен вместе, и я хотел бы сделать заказ с использованием MySQL. Это то, что я пытался, и под ним, вы найдете это объяснить также:
SELECT Ads.AdId FROM Ads, AdsHierarchy, AdsGeometry WHERE
Ads.AdId = AdsHierarchy.ads_AdId AND
AdsGeometry.AdId = Ads.AdId AND (
ST_CONTAINS(GeomFromText('Polygon((
-4.9783515930176 36.627100703563,
-5.0075340270996 36.61222072018,
-4.9896812438965 36.57638676015,
-4.965991973877 36.579419508882,
-4.955005645752 36.617732160006,
-4.9783515930176 36.627100703563
))'), AdsGeometry.GeomPoint) OR
AdsHierarchy.locations_LocationId = 148022797
)
GROUP BY Ads.AdId
id select_type table type possible_keys key key_len ref rows Extra
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 SIMPLE AdsGeometry ALL PRIMARY,GeomPoint,sx_adsgeometry_geompoint NULL NULL NULL 682848 Using temporary; Using filesort
1 SIMPLE Ads eq_ref PRIMARY PRIMARY 4 dbname.AdsGeometry.AdId 1 Using where; Using index
1 SIMPLE AdsHierarchy ref Ads_AdsHierarchy,locations_LocationId Ads_AdsHierarchy 4 dbname.Ads.AdId 1 Using where
Хотя этот запрос возвращает правильный набор результатов (68 строк), он нуждается в 6.5937 секунд для запуска. Если я это правильно понимаю, таблица AdsHierarchy
не использует его индексы, а также AdsGeometry
.
Есть ли способ объединить два запроса (или, возможно, даже больше местоположения или запросы на основе многоугольника, подобные этим), и поддерживать разумную скорость для его запуска?
Спасибо!
EDIT: Некоторая информация, о том, как индексы 3 таблицы в вопросе
AdsGeometry
таблица MyISAM и первичный ключ AdId
.
Результат SHOW INDEXES FROM AdsGeometry
является:
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
AdsGeometry 0 PRIMARY 1 AdId A 682848 NULL NULL BTREE
AdsGeometry 1 Latitude 1 Latitude A NULL NULL NULL BTREE
AdsGeometry 1 Longitude 1 Longitude A NULL NULL NULL BTREE
AdsGeometry 1 GeomPoint 1 GeomPoint A NULL 32 NULL SPATIAL
AdsGeometry 1 sx_adsgeometry_geompoint 1 GeomPoint A NULL 32 NULL SPATIAL
AdsGeometry 1 Latitude_2 1 Latitude A NULL NULL NULL BTREE
AdsGeometry 1 Latitude_2 2 Longitude A NULL NULL NULL BTREE
AdsHierarchy
тип таблицы InnoDB, первичный ключ AdsHierarchyId
.
Результат SHOW INDEXES FROM AdsHierarchy
является:
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
AdsHierarchy 0 PRIMARY 1 AdsHierarchyId A 2479044 NULL NULL BTREE
AdsHierarchy 1 Ads_AdsHierarchy 1 ads_AdId A 2479044 NULL NULL BTREE
AdsHierarchy 1 locations_LocationId 1 locations_LocationId A 123952 NULL NULL BTREE
Ads
тип таблицы InnoDB, первичный ключ AdId
.
Результат SHOW INDEXES FROM Ads
является:
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Ads 0 PRIMARY 1 AdId A 705411 NULL NULL BTREE
Ads 1 Accounts_Ads 1 accounts_AccountId A 2 NULL NULL BTREE
Ads 1 Ads_Locations 1 locations_LocationId A 88176 NULL NULL BTREE
Ads 1 Categories_Ads 1 categories_CategoryId A 16 NULL NULL BTREE
Ads 1 Currencies_Ads 1 currencies_Currency A 2 NULL NULL BTREE
Ads 1 countries_CountryId 1 countries_CountryId A 204 NULL NULL BTREE
Ads 1 ExternalId 1 ExternalId A 705411 NULL NULL BTREE
Ads 1 ExternalId 2 accounts_AccountId A 705411 NULL NULL BTREE
Ads 1 xml_XMLId 1 xml_XMLId A 4 NULL NULL BTREE
Ads 1 streets_StreetId 1 streets_StreetId A 2 NULL NULL YES BTREE
EDIT 2: Запрос переписан с неявным присоединяется, и объяснил:
Это запрос, переписанный с использованием неявной соединения, но он все еще работает очень медленно (5.503 сек)
SELECT a.AdId FROM Ads AS a
JOIN AdsHierarchy AS ah ON a.AdId = ah.ads_AdId
JOIN AdsGeometry AS ag ON a.AdId = ag.AdId
WHERE
ST_CONTAINS(GeomFromText('Polygon((
-4.9783515930176 36.627100703563,
-5.0075340270996 36.61222072018,
-4.9896812438965 36.57638676015,
-4.965991973877 36.579419508882,
-4.955005645752 36.617732160006,
-4.9783515930176 36.627100703563
))'), ag.GeomPoint)
OR ah.locations_LocationId = 148022797
GROUP BY a.AdId
id select_type table type possible_keys key key_len ref rows Extra
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 SIMPLE a index PRIMARY PRIMARY 4 NULL 627853 Using index
1 SIMPLE ag eq_ref PRIMARY,GeomPoint,sx_adsgeometry_geompoint PRIMARY 8 micasa_dev.a.AdId 1 Using index condition
1 SIMPLE ah ref Ads_AdsHierarchy,locations_LocationId Ads_AdsHierarchy 4 micasa_dev.a.AdId 1 Using where
EDIT 3: Испытание UNION-ки два запроса
Также пробовали UNION
метод, предоставленный @RobertKoch.
Хотя нижеследующее UNION
запрос выполняется очень быстро (0,06 секунд)
SELECT Ads.AdId FROM Ads, AdsGeometry
WHERE
AdsGeometry.AdId = Ads.AdId AND
ST_CONTAINS(GeomFromText('Polygon((
-4.9783515930176 36.627100703563,
-5.0075340270996 36.61222072018,
-4.9896812438965 36.57638676015,
-4.965991973877 36.579419508882,
-4.955005645752 36.617732160006,
-4.9783515930176 36.627100703563
))'), AdsGeometry.GeomPoint)
GROUP BY Ads.AdId
UNION
SELECT Ads.AdId FROM Ads, AdsHierarchy WHERE
Ads.AdId = AdsHierarchy.ads_AdId AND
AdsHierarchy.locations_LocationId = 148022797
GROUP BY Ads.AdId
Я до сих пор не может использовать этот метод, а потом мне нужно отсортировать набор результатов, которые я получаю от сращивать два запроса, основанные на таблице Ads
.
И если я пытаюсь сделать следующее дело, запрос снова становится экстремально медленно (3,7 секунды):
SELECT Ads.AdId FROM Ads WHERE Ads.AdId IN (
SELECT Ads.AdId FROM Ads, AdsGeometry
WHERE
AdsGeometry.AdId = Ads.AdId AND
ST_CONTAINS(GeomFromText('Polygon((
-4.9783515930176 36.627100703563,
-5.0075340270996 36.61222072018,
-4.9896812438965 36.57638676015,
-4.965991973877 36.579419508882,
-4.955005645752 36.617732160006,
-4.9783515930176 36.627100703563
))'), AdsGeometry.GeomPoint)
GROUP BY Ads.AdId
UNION
SELECT Ads.AdId FROM Ads, AdsHierarchy WHERE
Ads.AdId = AdsHierarchy.ads_AdId AND
AdsHierarchy.locations_LocationId = 148022797
GROUP BY Ads.AdId
) WHERE Ads.AdId > 100000
ORDER BY Ads.ModifiedDate ASC
EDIT 4: Изменение где UNION постоянно находится, по-видимому, чтобы решить эту проблему
Если я изменить выше UNION
запрос
SELECT Ads.AdId
FROM Ads,
(SELECT Ads.AdId
FROM Ads,
AdsGeometry
WHERE AdsGeometry.AdId = Ads.AdId
AND ST_CONTAINS(GeomFromText('Polygon((
-4.9783515930176 36.627100703563,
-5.0075340270996 36.61222072018,
-4.9896812438965 36.57638676015,
-4.965991973877 36.579419508882,
-4.955005645752 36.617732160006,
-4.9783515930176 36.627100703563
))'), AdsGeometry.GeomPoint)
GROUP BY Ads.AdId
UNION SELECT Ads.AdId
FROM Ads,
AdsHierarchy
WHERE Ads.AdId = AdsHierarchy.ads_AdId
AND AdsHierarchy.locations_LocationId = 148022797
GROUP BY Ads.AdId) AS nt
WHERE Ads.AdId = nt.AdId
AND Ads.AdId > 1000000
ORDER BY Ads.ModifiedDate ASC
запрос затем выполняется быстро снова (~ 0.0 007 секунд).
Если никакое решение не приходит без
UNION
, я готов дать награду любому, кто может объяснить разницу между этими двумяUNION
версий (это один и тот в EDIT 3), и объясните мне , почему запрос выполняется быстро, когда он написан в следующем порядке и работает медленно, когда он написан в указанном выше порядке.
Если вам нужна дополнительная информация, просьба указать в комментариях, и я стараюсь их предоставить! Спасибо
* ПРИМЕЧАНИЕ: * Я добавил ORDER к двум запросам UNION, чтобы сделать его более ясным, что, хотя я только выбираю AdId
из таблиц, мне все еще нужны другие поля из таблицы Ads
.
EDIT 5: запрос @bovko
1 SIMPLE Ads index NULL countries_CountryId 2 NULL 627853 Using index; Using temporary
1 SIMPLE ag eq_ref PRIMARY PRIMARY 8 micasa_dev.Ads.AdId 1 Using where; Distinct
1 SIMPLE ah ref Ads_AdsHierarchy Ads_AdsHierarchy 4 micasa_dev.Ads.AdId 1 Using where; Distinct
Вы посмотрели план запроса, чтобы узнать, откуда идет замедление. ? – Doon
Попробуйте «СОЮЗ» оба запроса. Он должен автоматически отфильтровывать дубликаты. –
@RobertKock Я думал об UNION-ing, но у меня очень плохой опыт работы с UNION, это действительно единственный способ решить эту проблему? –