回答編集履歴

12

加筆

2021/05/17 01:19

投稿

退会済みユーザー
test CHANGED
@@ -169,3 +169,39 @@
169
169
  ネット上に誰かが作ったデータがあるかもしれませんし、
170
170
 
171
171
  自分でQGISを使って作ることもできますね。
172
+
173
+
174
+
175
+ ---
176
+
177
+
178
+
179
+ あー、php上で配列要素から配列要素に、
180
+
181
+ ループを回して代入するのは、ほんとに無駄なことをやってますね。
182
+
183
+ それを2万件も回しているかと思うと呆れてきます。
184
+
185
+
186
+
187
+ そういうことは、データベースに任せてください。
188
+
189
+ クエリーの仕事です。
190
+
191
+ とてもphp上でやるべきことではない。
192
+
193
+ つまり、テーブル同士を欲しい情報のカタチにouter joinして
194
+
195
+ データの結合をデータベース内にやらせてください。
196
+
197
+ 適材適所というか、データの並べ替えや整理が得意なデータベースの仕事を
198
+
199
+ わざと不得意なphpにやらせてるのが悪いです。
200
+
201
+
202
+
203
+ outer joinでテーブルのデータ構造の主従関係に沿って連結して、
204
+
205
+ ほしい並び順はorder by句でコントロール。
206
+
207
+ それができれば、単にfetchAll()で完結しませんかね。

11

加筆

2021/05/17 01:19

投稿

退会済みユーザー
test CHANGED
@@ -149,3 +149,23 @@
149
149
  配列で保持できるようであれば、
150
150
 
151
151
  implode()を使って配列を文字列に連結するようにしたらよいかと。
152
+
153
+
154
+
155
+ それと余談。
156
+
157
+ 狭いところに2万件もプロットする見せ方も、考え直すべきですね。
158
+
159
+ 先の空間データ型を使うようになると、
160
+
161
+ 地域(例えば市町村、大字、町丁目とか)の形をMULTIPOLYGON型で格納したテーブルを用意すると、
162
+
163
+ A市に含まれるPOIが何件、B市に含まれるPOIが何件、
164
+
165
+ みたいなクエリーも作れます。
166
+
167
+ 何個も何十個もプロットせず、ざっくり数字だけ表示しておいて省略表示するべきでしょうね。
168
+
169
+ ネット上に誰かが作ったデータがあるかもしれませんし、
170
+
171
+ 自分でQGISを使って作ることもできますね。

10

加筆

2021/05/13 14:45

投稿

退会済みユーザー
test CHANGED
@@ -69,3 +69,83 @@
69
69
  2万件が相手だとしても、サーバーのチューニングも含めて徹底的に手を施すと
70
70
 
71
71
  クエリーだけなら6秒以上待たせる場面は減らせそうな気がする。(独断と偏見。)
72
+
73
+
74
+
75
+ ---
76
+
77
+
78
+
79
+ クエリー3種類、それをphpコードでどう処理しているのか、
80
+
81
+ っていうところも見たかったですが。
82
+
83
+
84
+
85
+ 緯度経度を伴うテーブルの、緯度経度を文字列のまま保持しているんでしょうか?
86
+
87
+ mysqlでもpostgresqlでも空間情報を扱う機能があるので、
88
+
89
+ 然るべき測地系の空間データとして格納し、
90
+
91
+ 空間インデックスを仕込むべきです。
92
+
93
+
94
+
95
+ [MySQL :: MySQL 5.6 リファレンスマニュアル :: 11.5 空間データの拡張](https://dev.mysql.com/doc/refman/5.6/ja/spatial-extensions.html)
96
+
97
+ この近辺をよく読んで、空間データとして扱えるよう変換したテーブルを作って変換してください。
98
+
99
+ 参考になる記事:[【MySQL】Geometry型で位置情報を扱う - Qiita](https://qiita.com/nkojima/items/bb21c72858606dedd817)
100
+
101
+
102
+
103
+ それと。
104
+
105
+ shop_table.idに対してshopimg_table.idは複数、
106
+
107
+ 同じく
108
+
109
+ shop_table.idに対してmenu_table.idも複数、
110
+
111
+ っていう感じでしょうか。
112
+
113
+ クエリー結果をもとにループしている中で、
114
+
115
+ 別のクエリーを実行するのは、あまり良くないような。
116
+
117
+ プリペアドステートメントの仕組みを使って、
118
+
119
+ パラメータのみ変えて実行するならまだSQL文の解釈にかかる処理時間を省くことができますが、
120
+
121
+ もしも、一番外側のループの値を都度、SQL文に文字列連結してクエリーを作っているなら、
122
+
123
+ 即刻やめて
124
+
125
+ [PDO::prepare](https://www.php.net/manual/ja/pdo.prepare.php)
126
+
127
+ [PDOStatement::bindValue](https://www.php.net/manual/ja/pdostatement.bindvalue.php)
128
+
129
+ [PDOStatement::execute](https://www.php.net/manual/ja/pdostatement.execute.php)
130
+
131
+ を組み合わせてプリペアドステートメントによるクエリー実行に直します。
132
+
133
+
134
+
135
+ [PHPでデータベースに接続するときのまとめ - Qiita](https://qiita.com/mpyw/items/b00b72c5c95aac573b71)
136
+
137
+ をなぞって、prepare→bindValue→executeの流れを丁寧にやるといいです。
138
+
139
+
140
+
141
+ 最後に、
142
+
143
+ 出力用のjson文字列を作るのに、最後にjson_encode()にかけるとして
144
+
145
+ その直前までひとつの文字列変数に文字列連結して文字列連結して文字列連結してってやり方をしていると、
146
+
147
+ パフォーマンスが落ちるかもしれません。
148
+
149
+ 配列で保持できるようであれば、
150
+
151
+ implode()を使って配列を文字列に連結するようにしたらよいかと。

9

見直し

2021/05/13 14:39

投稿

退会済みユーザー
test CHANGED
@@ -49,3 +49,23 @@
49
49
  自前で処理を起こさず、仕組み建てを変えてみるのも良いかと。
50
50
 
51
51
  サーバーサイドが明るくないのであればなおさら。
52
+
53
+
54
+
55
+ とはいえ、仕組みをいじるのは腰が重いでしょうから、
56
+
57
+ データベース周りをしっかりやってほしいかな、
58
+
59
+ ヘボいクエリーを叩き直すことで応答までの時間がケタ1つ2つ変わるなんて話はよくあるし。
60
+
61
+ 主キー設定してますか、
62
+
63
+ テーブルをJOINするお互いのキーにインデックスはありますか、
64
+
65
+ JOINするときに関数で加工しているなら止めましょうね、
66
+
67
+ 全部を一度の連結しなくても、情報を小出しにして何度も取得しに行くよう、一度に取得するデータの粒度を小さくするアルゴリズムを考えるのも大事。
68
+
69
+ 2万件が相手だとしても、サーバーのチューニングも含めて徹底的に手を施すと
70
+
71
+ クエリーだけなら6秒以上待たせる場面は減らせそうな気がする。(独断と偏見。)

8

見直し

2021/05/12 06:13

投稿

退会済みユーザー
test CHANGED
@@ -40,7 +40,7 @@
40
40
 
41
41
  Googleマップを表示したいからGoogle Map APIを使うというのはある意味正しいですが、
42
42
 
43
- OpenLayersとかLeafletなどの地図を扱えるjsライブラリを組み合わせつつ、
43
+ Mapbox GL JS(有料)やOpenLayersとかLeafletなどの地図を扱えるjsライブラリを組み合わせつつ、
44
44
 
45
45
  サーバー側も然るべき仕組み(MapServerとか)を組み合わせることで、
46
46
 

7

見直し

2021/05/12 06:06

投稿

退会済みユーザー
test CHANGED
@@ -26,10 +26,26 @@
26
26
 
27
27
  のように空間情報のためのインデックスもあるので、
28
28
 
29
- 例えばマップ表示中の中心の緯度経度情報を元に、
29
+ 例えばマップ表示中の中心の緯度経度情報を元に、
30
30
 
31
31
  表示範囲に相当する範囲のPOIだけ抽出して送信する、
32
32
 
33
33
  みたいなクエリーだってできるはず。
34
34
 
35
35
  いきなり2万件送信するんじゃなくて。
36
+
37
+
38
+
39
+ それと、
40
+
41
+ Googleマップを表示したいからGoogle Map APIを使うというのはある意味正しいですが、
42
+
43
+ OpenLayersとかLeafletなどの地図を扱えるjsライブラリを組み合わせつつ、
44
+
45
+ サーバー側も然るべき仕組み(MapServerとか)を組み合わせることで、
46
+
47
+ 表示範囲に限定した情報のみ非同期に取得して地図情報反映する仕組みが実現しやすいです。
48
+
49
+ 自前で処理を起こさず、仕組み建てを変えてみるのも良いかと。
50
+
51
+ サーバーサイドが明るくないのであればなおさら。

6

加筆

2021/05/12 06:01

投稿

退会済みユーザー
test CHANGED
@@ -17,3 +17,19 @@
17
17
  処理の区切りごとにmicrotime(true)で測定して比較するとか。
18
18
 
19
19
  [PHPの処理速度を計測 - Qiita](https://qiita.com/ao_love/items/a2d8b8566d0426195002)
20
+
21
+
22
+
23
+ それと、
24
+
25
+ [MySQL :: MySQL 5.6 リファレンスマニュアル :: 11.5.3.5 空間分析の最適化](https://dev.mysql.com/doc/refman/5.6/ja/optimizing-spatial-analysis.html)
26
+
27
+ のように空間情報のためのインデックスもあるので、
28
+
29
+ 例えばマップ表示中の中心店の緯度経度情報を元に、
30
+
31
+ 表示範囲に相当する範囲のPOIだけ抽出して送信する、
32
+
33
+ みたいなクエリーだってできるはず。
34
+
35
+ いきなり2万件送信するんじゃなくて。

5

見直し

2021/05/12 04:28

投稿

退会済みユーザー
test CHANGED
@@ -5,3 +5,15 @@
5
5
 
6
6
 
7
7
  インデックスが適切に施されていない、あるいは施されていても効いていないって話かと。
8
+
9
+
10
+
11
+ それと、コードを見ていないので当てずっぽう感ありますが、
12
+
13
+ 2万件をどうやってjsonに加工しているのか。
14
+
15
+ 文字列の連結を都度繰り返すのか、implode()で一発で連結するのかとか、
16
+
17
+ 処理の区切りごとにmicrotime(true)で測定して比較するとか。
18
+
19
+ [PHPの処理速度を計測 - Qiita](https://qiita.com/ao_love/items/a2d8b8566d0426195002)

4

見直し

2021/05/12 02:26

投稿

退会済みユーザー
test CHANGED
File without changes

3

加筆

2021/05/12 02:26

投稿

退会済みユーザー
test CHANGED
File without changes

2

加筆

2021/05/12 02:23

投稿

退会済みユーザー
test CHANGED
@@ -1,3 +1,7 @@
1
1
  SQLの実行計画のチェック。
2
2
 
3
3
  [MySQL :: MySQL 5.6 リファレンスマニュアル :: 8.8.1 EXPLAIN によるクエリーの最適化](https://dev.mysql.com/doc/refman/5.6/ja/using-explain.html)
4
+
5
+
6
+
7
+ インデックスが適切に施されていない、あるいは施されていても効いていないって話かと。

1

加筆

2021/05/12 02:23

投稿

退会済みユーザー
test CHANGED
File without changes