質問ファースト
SQLite データベースをできるだけ早く検索するにはどうすればよいですか?
Excel で 60,000 行すべての住所データを解析し、それらをリストにロードしてから、一度にすべてを検索する必要がありますか?
単純にプレーン テキスト ファイルに目を通すことから切り替えることで、スクリプトが 3 倍高速化されましたが、それでももっと高速になる可能性があると思います。
前もって感謝します!
データベース
Geonames の郵便番号データ ダンプから作成した都市名、郵便番号、座標などの SQLite データベースがあります: Geonames Postal Codes
データベースには国ごと (DE、US、GB など、全部で 72) のテーブルがあり、これらの各テーブルには、次の形式で、それぞれ数十から数万の行があります。
country code : iso country code, 2 characters
postal code : varchar(20)
place name : varchar(180)
admin name1 : 1. order subdivision (state) varchar(100)
admin code1 : 1. order subdivision (state) varchar(20)
admin name2 : 2. order subdivision (county/province) varchar(100)
admin code2 : 2. order subdivision (county/province) varchar(20)
admin name3 : 3. order subdivision (community) varchar(100)
admin code3 : 3. order subdivision (community) varchar(20)
latitude : estimated latitude (wgs84)
longitude : estimated longitude (wgs84)
accuracy : accuracy of lat/lng from 1=estimated to 6=centroid
ワークフロー
現在、Python での私の現在のスクリプトは次のようになります。
- Excel ファイルの行を読み取る
- 住所と位置データを解析する (その間にある他の多くの無関係なもの)
- SQLite データベースで一致を検索する
- SQLite db の一致する行からの情報を .CSV ファイルに書き込みます
Excel ファイルは約 60,000 行あり、行ごとに Python スクリプト全体 (上記のプロセス) を実行します。
私の住所データは非常に一貫性がなく、郵便番号、都市名、国名が混在しています。このデータのすべてが Excel の行にある場合もあれば、そうでない場合もあります。また、多くのスペルミスや別名が付属しています。
データに一貫性がなく、一致しない郵便番号や市区町村を入力する人もいるため、現在、Python スクリプトで次のようなさまざまな検索クエリを試しています。
- [郵便番号] が列と完全に一致し、かつ [地名] が列と完全に一致するかどうかを確認します
- [郵便番号] が列と完全に一致し、かつ列の [地名] と一致するかどうかを確認します
- [郵便番号] が列と完全に一致し、列の [場所名] (単語ごとに分割) が一致するかどうかを確認します
- [郵便番号] だけが列と一致するかどうかを確認します
Python スクリプト
これが Python スクリプトのセクションです。ご覧のとおり、かなり非効率的です。
if has_country_code == True:
not_in_list = False
country = country_code.lower()+"_"
print "HAS COUNTRY"
if has_zipcode == True and has_city_name == True:
print "HAS COUNTRY2"
success = False
try:
curs = conn.execute("SELECT * FROM "+country+" WHERE postal_code = ? AND place_name = ? COLLATE NOCASE", (zipcode, city,))
for row in curs:
success = True
break
except:
not_in_list = True
success = True
if success != True:
curs = conn.execute("SELECT * FROM "+country+" WHERE postal_code = ? AND place_name LIKE ? COLLATE NOCASE", (zipcode,"%"+city+"%",))
for row in curs:
success = True
break
if success != True:
newCity = ""
newCity = filter(None,re.split('[; / ( ) - ,]',city))
questionMarks = ",".join(["?" for w in newCity])
curs = conn.execute("SELECT * FROM "+country+" WHERE postal_code = ? AND place_name IN ("+questionMarks+") COLLATE NOCASE", ([zipcode]+newCity))
for row in curs:
success = True
break
if success != True:
curs = conn.execute("SELECT * FROM "+country+" WHERE postal_code = ? COLLATE NOCASE", (zipcode,))
for row in curs:
success = True
break
if success != True:
curs = conn.execute("SELECT * FROM "+country+" WHERE place_name = ? COLLATE NOCASE", (city,))
for row in curs:
success = True
break
if success != True:
curs = conn.execute("SELECT * FROM "+country+" WHERE place_name LIKE ? COLLATE NOCASE", ("%"+city+"%",))
for row in curs:
success = True
break
if success != True:
newCity = ""
newCity = filter(None,re.split('[; / ( ) - ,]',city))
questionMarks = ",".join(["?" for w in newCity])
curs = conn.execute("SELECT * FROM "+country+" WHERE place_name IN ("+questionMarks+") COLLATE NOCASE", (newCity))
for row in curs:
success = True
break
if success != True:
newCity = ""
newCity = filter(None,re.split('[; / ( ) - ,]',city))
newCity.sort(key=len, reverse=True)
newCity = (["%"+w+"%" for w in newCity])
for item in newCity:
curs = conn.execute("SELECT * FROM "+country+" WHERE place_name LIKE (?) COLLATE NOCASE", (item,))
for row in curs:
success = True
break
break
if has_city_name == True and has_zipcode == False:
try:
curs = conn.execute("SELECT * FROM "+country+" WHERE place_name = ? COLLATE NOCASE", (city,))
for row in curs:
success = True
break
except:
not_in_list = True
success = True
if success != True:
curs = conn.execute("SELECT * FROM "+country+" WHERE place_name LIKE ? COLLATE NOCASE", ("%"+city+"%",))
for row in curs:
success = True
break
if success != True:
newCity = ""
newCity = filter(None,re.split('[; / ( ) - ,]',city))
questionMarks = ",".join(["?" for w in newCity])
curs = conn.execute("SELECT * FROM "+country+" WHERE place_name IN ("+questionMarks+") COLLATE NOCASE", (newCity))
for row in curs:
success = True
break
if success != True:
newCity = ""
newCity = filter(None,re.split('[; / ( ) - ,]',city))
newCity.sort(key=len, reverse=True)
newCity = (["%"+w+"%" for w in newCity])
for item in newCity:
curs = conn.execute("SELECT * FROM "+country+" WHERE place_name LIKE (?) COLLATE NOCASE", (item,))
for row in curs:
success = True
break
break
if has_city_name == False and has_zipcode == True:
try:
curs = conn.execute("SELECT * FROM "+country+" WHERE postal_code = ?", (zipcode,))
for row in curs:
success = True
break
except:
not_in_list = True
success = True