2009-10-02 3 views
0

Я хотел бы знать, как оптимизировать следующий SQL, чтобы мой сервер быстрее загружался и пользовался низким уровнем использования?Как оптимизировать мой SQL-сервер?

Мне нужно рассчитать радиус радиуса для почтового индекса США, чтобы получить результат, например, в 50 милях от определенного почтового индекса (с использованием широты и долготы для расчета) и получения количества других данных (например, других почтовых индексов) из моей базы данных.

Как только я получу результат (например, получил 350 строк разных ZIP-кодов в пределах 50 миль от определенного почтового индекса), мне нужно передать их в другой запрос, чтобы подсчитать полные строки и отобразить их простым и одним результатом для мне читать. Вот пример моего запроса:

SELECT count(*) 
FROM 
(SELECT b.ID, ROUND((acos(sin(3.142/180*32.91336) * sin(3.142/180*z.latitude) + cos(3.142/180*32.91336) * cos(3.142/180*z.latitude) * cos((3.142/180*z.longitude) - (3.142/180*-85.93836))) * 3959),2) AS distance 
    FROM zipcode2business.accountants b LEFT JOIN zipcodeworld.storelocator_us z ON b.ZIPCODE = z.ZIP_CODE 
    WHERE z.latitude != 32.91336 AND z.longitude != -85.93836 
    AND b.STATE='AL' 
    HAVING distance between 0 AND 50) 
as total; 

Надеюсь, я не сделал неправильно, он показывает правильный результат (350 строк), но мне нужен оптимизированный способ работает, потому что это SQL дал мне высокую загрузку процессора загружать. Когда я EXPLAIN для этого запроса, то отобразить следующее:

+----+-------------+-------+--------+------------------+---------+---------+----------------------------+------+------------------------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref      | rows | Extra      | 
+----+-------------+-------+--------+------------------+---------+---------+----------------------------+------+------------------------------+ 
| 1 | PRIMARY  | NULL | NULL | NULL    | NULL | NULL |  NULL    | NULL | Select tables optimized away | 
| 2 | DERIVED  | b  | ref | ZIPCODE,STATE | STATE | 4  |       | 3900 | Using where     | 
| 2 | DERIVED  | z  | eq_ref | PRIMARY,LAT_LONG | PRIMARY | 9  | zipcode2business.b.ZIPCODE | 1 | Using where     | 
+----+-------------+-------+--------+------------------+---------+---------+----------------------------+------+------------------------------+ 
3 rows in set (0.20 sec) 

Теперь из приведенных выше объяснений, «Выбор таблицы оптимизированной прочь» в EXTRA хорошая вещь? Пожалуйста, любезно покажите мне одну наиболее совершенную оптимизацию SQL для выполнения этого запроса.

ответ

0

Вам нужно делать все эти вычисления на сервере sql? Обычно я пытаюсь использовать SQL для базового CRUD с данными, тогда все остальные вычисления выполняются вне SQL. Вы можете попытаться получить данные, на которых базируются ваши расчеты, а затем выполнить фактический расчет с тем, что извлекает данные.

1

SQL, собственно, кажется, хорошо, большая часть процессорного времени должны быть потрачены делать математику ... Есть два пути для оптимизации

  • упрощения формул
  • отфильтровывает строки рано (» подрезать "), на основе еще более простого расчета

у меня нет времени на данный момент для получения полной информации, но здесь общая идея:
Она должна приблизительной в расстояние от ссылочного местоположения ZipCode и других мест, с дешевым (процессорным) вычислением, и только делать полную математику (с лучшей формулой, чем та, что в исходном запросе), для местоположений, которые находятся ниже 50 миль (+ небольшой дополнительный, для учета возможной недооценки).

Оценка расстояния и обрезку
Вычислим, раз, расстояние в милях expessed, соответствующее одному градусу широты и один градус долготы, от местоположения опорного ZipCode; назовите эти MpDLat и MpDLong. Возможно, мы вычисляем дробное значение степени, соответствующее нашему целевому радиусу от ссылочного местоположения; назовите эти Dp50Lat и Dp50Long. Затем работайте с [абсолютной величиной] разницы между широтами и между долготами относительно исходного местоположения и отфильтровывайте места, для которых это расстояние в одном направлении (лат или долго) превышает наш предел. то естьчто-то вроде следующего

WHERE .... (some other condidtions....) 
    AND (abs(z.latitude - 32.91336) * MpDLat) < 50 
    AND (abs(z.longitude + 85.93836) * MpDLong) < 50 
--or, if we got by the Dp50 values 
WHERE .... (some other condidtions....) 
    AND (abs(z.latitude - 32.91336) < Dp50Lat 
    AND (abs(z.longitude + 85.93836) < Dp50Long 

Расчет расстояния (ибо там места не легко отфильтрованы)
В зависимости от уровня требуемой точности может быть приемлемо, чтобы придерживаться факторов MPD (я предполагаю, что ошибки менее одной мили или около того, для расстояний порядка 50 миль в пределах континентальной части США). Тогда расстояния будут рассчитываться как: Sqrt ((z.latitude - 32.91336)^2 + (z.longitude + 85.93836)^2 или, если нас интересует только их фильтрация, без необходимости в расчете как таковом, мы может работать от квадратов, т.е. ... WHERE (z.latitude - 32,91336)^2 + (z.longitude + 85,93836)^2 < 2500 - 2509 составляет 50^2

Я предполагаю, что этот тип аппроксимации приемлемо, так как гораздо большие ошибки сделаны с учетом того, что расстояние по дорогам (что, вероятно, в конечном итоге требуется) редко совпадает с расстоянием «как-ворона-мухи» ;-) Я могу рассчитать точное худший случай потери точности (но опять же, нет времени для этого сейчас ...)

Если требуется точное расстояние, мы используем немного лучшую формулу, что оригинал, этот, кажется, непосредственно получен из сферического закона косинуса. Возможно, мы сможем сделать лучше.

Вариации на вышеуказанных
Рассмотренные выше идеи могут быть реализованы в различных моды, например, с использованием временных таблиц SQL или различных конструкций для запроса (ий) и т.д.

0

вас может выбрать вычисление расстояния в таблице temp и удалить HAVING из вашего SQL, а затем выполнить второй SELECT WHERE dist < = 50

Это помогает экономить пространство памяти и позволяет сворачивать на временные сегменты диска для большого количества записей в ваш базовый стол

Смежные вопросы